# 类的装饰器
# 对不同的类使用装饰器加上不同的类属性
def typed(**kwargs):
def deco(obj):
for k, v in kwargs.items():
setattr(obj, k, v)
return obj
return deco
@typed(x=1, y=2, z=3) # 1、typed(x=1, y=2, z=3)->deco 2、@deco->Foo=deco(Foo)
class Foo:
pass
print(Foo.__dict__)
@typed(name='alex')
class Bar:
pass
print(Bar.__dict__)
# 通过类的装饰器再对描述符检测数据类型的例子进行改写
class Typed: # 定义描述符的类,必须是一个数据描述符
def __init__(self, key, expected_type): # 定义一个实例化方法,主要用于传实例字典的key,和期望的数据类型
self.key = key
self.expected_type = expected_type
def __get__(self, instance, owner):
# instance 代表实例(p1) owener代表实例的拥有者(People)
return instance.__dict__[self.key] # 返回实例字典key的值
def __set__(self, instance, value):
# instance 代表实例(p1) value代表传入的值
if not isinstance(value, self.expected_type): # 判断用户传入的name如果不是字符串
print('你传入的类型不是%s' % self.expected_type)
return # return终止此方法,不执行下面的赋值
instance.__dict__[self.key] = value
def classtyped(**kwargs): # kwargs={'name':'str', 'age':'int', 'salary':'float'}
def deco(obj): # obj=People
for k, v in kwargs.items(): # (('name', str), ('age', int), ('salary', float))
setattr(obj, k, Typed(k, v)) # setattr(People, 'name', Typed('name', str))
return obj
return deco
@classtyped(name=str, age=int, salary=float)
class People:
def __init__(self, name, age, salary):
self.name = name
self.age = age
self.salary = salary
p1 = People('alex', 18, 2584.25)
print(p1.__dict__) # {'name': 'alex', 'age': 18, 'salary': 2584.25}
p1.name = 'egon'
print(p1.__dict__) # {'name': 'egon', 'age': 18, 'salary': 2584.25}