描述器定义方式一:
class Person:
def __init__(self):
self.__age = 18
def get_age(self):
return self.__age
def set_age(self, value):
if 0 <= value <= 200:
self.__age = value
def del_age(self):
del self.__age
age = property(get_age, set_age, del_age)
p = Person()
print(p.age)
p.age = 20
print(p.age)
print(p.__dict__)
del p.age
print(p.__dict__)
#运行结果
18
20
{'_Person__age': 20}
{}
class Person:
def __init__(self):
self.__age = 18
@property
def age(self):
return self.__age
@age.setter
def age(self, value):
if isinstance(value, int) and 0 <= value <= 200:
self.__age = value
else:
print("value 的值设置错误,你输如正确的数值 ")
@age.deleter
def age(self):
del self.__age
p = Person()
print(p.age)
p.age = 20
print(p.age)
print(p.__dict__)
del p.age
print(p.__dict__)
#运行结果
18
20
{'_Person__age': 20}
{}
描述器定义方式二:
# 如果实现了 __get__ ,__set__ ,判定为"资料描述器"
# 如果只实现了 _get__ , 判定为"非资料描述器"
# 描述器和实例属性同名时, 操作的优先级问题
# 资料描述器 > 实例字典 > 非资料描述器
# 描述器仅在新式类中生效
class Age:
def __get__(self, instance, owner):
return instance.v
def __set__(self, instance, value):
instance.v = value
def __delete__(self, instance):
del instance.v
class Person:
age = Age()
def __init__(self, age):
self.age = age
p = Person(20)
print(p.age)
print(p.__dict__)
del p.age
print(p.__dict__)
#运行结果
20
{'v': 20}
{}
PS1:
一个实例属性的正常访问顺序
实例对象自身的dict字典
对应类对象的dict字典
如果有父类, 会再往上层的dict字典中检测
如果没找到, 又定义了getattr方法, 就会调用这个方法
PS2:
而在上述的整个过程当中, 是如何将描述器的get方法给嵌入到查找机制当中?
就是通过这个方法进行实现 __getattribute__
内部实现模拟:
如果实现了描述器方法get就会直接调用
如果没有, 则按照上面的机制去查找
装饰器:
def check(func):
def inner():
print("check")
func()
return inner
@check
def fss():
print("发说说")
# fss = check(fss)
fss()
使用类当做装饰器来使用
class check:
def __init__(self, func):
self.f = func
def __call__(self, *args, **kwargs):
print("check")
self.f()
def fss():
print("发说说")
fss = check(fss)
fss()