话不多说,上代码,看结果。
print('2.6.1.7、描述器##############################')
# 概念 可以描述一个属性操作的对象
# 属性的操作 增/改 删 查
# 作用
# 可以代为管理一个类属性的读写删操作, 在相关方法中, 对数据进行验证处理, 过滤处理等等
# 如果一个类属性被定义为描述器,那么以后对这个类属性的操作(读写删), 都将由这个描述器代理
# 定义
# 定义方式1 property
class Forest:
def __init__(self):
self._animal = '熊大'
self._animal2 = '熊二'
@property
def animal(self):
return self._animal
@animal.setter
def animal(self, value):
self._animal = value
@animal.deleter
def animal(self):
del self._animal2
b1 = Forest()
print(b1.__dict__)
print(b1.animal)
b1.animal = "虫大"
print(b1.animal)
del b1.animal
print(b1.__dict__)
# 定义方式2 三个方法 __get__ __set__ __delete__
# 调用细节
# 使用实例进行调用 最多三个方法都会被调用
# 使用类进行调用 最多会调用get方法
class Pinpai:
def __get__(self, instance, value):
print('get')
def __set__(self, instance, value):
print('set')
def __delete__(self, instance):
print('del')
class Computer:
pinpai = Pinpai()
com = Computer()
com.pinpai = '戴尔'
print(com.pinpai)
del com.pinpai
print('~~~~')
print(Computer.pinpai)
Computer.pinpai = '戴尔'
del Computer.pinpai
# 不能够顺利转换的场景
# 新式类和经典类 描述器仅在新式类中生效
# 方法拦截
# 一个实例属性的正常访问顺序
# 实例对象自身的__dict__字典
# 对应类对象的__dict__字典
# 如果有父类, 会再往上层的__dict__字典中检测
# 如果没找到, 又定义了__getattr__方法, 就会调用这个方法
# 而在上述的整个过程当中, 是如何将描述器的__get__方法给嵌入到查找机制当中?
# 就是通过这个方法进行实现 __getattribute__
# 内部实现模拟
# 如果实现了描述器方法__get__就会直接调用
# 如果没有, 则按照上面的机制去查找
class Computer1:
pinpai = Pinpai()
def __getattribute__(self, item):
print('******')
com = Computer1()
com.pinpai = '戴尔'
print(com.pinpai)
del com.pinpai
# 注意 "资料描述器"和"非资料描述器"
# 如果实现了 __get__ 判定为"非资料描述器"
# 如果实现了 __get__ __set__ 判定为"资料描述器"
# 描述器和实例属性同名时, 操作的优先级问题 资料描述器 > 实例字典 > 非资料描述器
class Computer2:
pinpai = Pinpai()
def __init__(self):
self.pinpai = '苹果'
com1 = Computer2()
com1.pinpai = '戴尔'
print('...', com1.pinpai)
print(com1.__dict__)
# 存储问题
class Level:
def __get__(self, instance, owner):
print("get")
return instance.v
def __set__(self, instance, value):
print("set", self, instance, value)
instance.v = value
def __delete__(self, instance):
print("delete")
del instance.v
class Game:
level = Level()
game = Game()
game.level = 10
print(game.level)
game2 = Game()
game2.level = 11
print(game2.level)
print(game.level)
# 装饰器 使用类当做装饰器来使用
def fun8(func):
def inner():
print('#######')
func()
return inner
@fun8 # fun7 = fun8(fun7)
def fun7():
print('fun7')
fun7()
class fun8:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print('#######')
self.func()
@fun8 # fun7 = fun8(fun7)
def fun7():
print('fun7')
fun7()
结果如下图
就先这样,遇到别的再补充。