类的装饰器

一切皆对象

语法糖@可以用在函数上,也可以用在类上

函数也是一种对象,也有属性字典,也可以给属性赋值等操作

def deco(obj):
    obj.x = 1
    obj.y = 2
    return obj

@deco   #相当于Foo = deco(Foo)
class Foo:
    pass
print(Foo.__dict__)

@deco    #相当于test = deco(test)
def test():
    pass
print(test.__dict__)

输出:
{‘module’: ‘main’, ‘dict’: <attribute ‘dict’ of ‘Foo’ objects>, ‘weakref’: <attribute ‘weakref’ of ‘Foo’ objects>, ‘doc’: None, ‘x’: 1, ‘y’: 2}
{‘x’: 1, ‘y’: 2}

def Typed(**kwargs):
    def deco(obj):
        for key,value in kwargs.items():
            setattr(obj,key,value)    #这里不能用obj.__dict__[key]=value设置属性,因为obj.__dict__不一定是字典类型,也可能是<class 'mappingproxy'>
        return obj
    return deco

@Typed(x=1,y=2)     #先执行Typed函数,返回值deco再和@组成@deco,相当于再执行Foo=deco(Foo)
class Foo:
    pass
print(Foo.__dict__)   #类的属性字典本质不是字典,而是<class 'mappingproxy'>映射代理

@Typed(name='alex')
def test():
    pass

print(test.__dict__)   #函数的属性字典和实例化的属性字典都是dict类型

输出:
{‘module’: ‘main’, ‘dict’: <attribute ‘dict’ of ‘Foo’ objects>, ‘weakref’: <attribute ‘weakref’ of ‘Foo’ objects>, ‘doc’: None, ‘x’: 1, ‘y’: 2}
{‘name’: ‘alex’}

描述符和类的装饰器结合使用

class Typed:   #描述符(类型限制)
    def __init__(self,key,expected_type):
        self.key = key
        self.expected_type = expected_type
    def __get__(self, instance, owner):
        return instance.__dict__[self.key]
    def __set__(self, instance, value):
        if not isinstance(value,self.expected_type):
            raise TypeError('%s传入的类型不是%s'%(value,self.expected_type))
        instance.__dict__[self.key] = value
    def __delete__(self, instance):
        print(instance.__dict__.pop(self.key))

def deco(**kwargs):    #类的装饰器(传字典)
    def wrapper(obj):
        for key,value in kwargs.items():
            setattr(obj,key,Typed(key,value))    #给Movie设置属性,key是属性名,值是描述符
        return obj
    return wrapper

@deco(title=str,rating=int,runtime=int,budget=int,gross=int)
class Movie:
    def __init__(self, title, rating, runtime, budget, gross):
        self.title = title
        self.rating = rating
        self.runtime = runtime
        self.budget = budget
        self.gross = gross

d1 = Movie('电影名称',456,24,100000,200000)

print(Movie.__dict__)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值