一切皆对象
语法糖@可以用在函数上,也可以用在类上
函数也是一种对象,也有属性字典,也可以给属性赋值等操作
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__)