|
发表于 2023-1-9 17:26:13
|
显示全部楼层
本帖最后由 Ensoleile 于 2023-1-10 00:27 编辑
描述符及property()实现原理
- #描述符(property的原理):P177 实现了__get__()/__set__()/__delete__()三个中任何一个或多个方法的类,称为描述符
- class D:
- def __get__(self, instance, owner):
- print(f'get~\nself -> {self}\ninstance -> {instance}\nowner -> {owner}')
- def __set__(self, instance, value):
- print(f'set~\nself -> {self}\ninstance -> {instance}\nvalue -> {value}')
- def __delete__(self, instance):# 不要混淆__del__()
- print(f'delete~\nself -> {self}\ninstance -> {instance}')
- # 类D 为描述符,在另一个类里将他的实例化对象赋值给想要管理的属性就能启用他
- class C:
- x = D()
- c = C()
- c.x = 250
- # set~
- # self -> <__main__.D object at 0x0000028D56A88FA0>
- # instance -> <__main__.C object at 0x0000028D56A88F70>
- # value -> 250
- c.x
- # get~
- # self -> <__main__.D object at 0x0000026F6A728FA0>
- # instance -> <__main__.C object at 0x0000026F6A728F70>
- # owner -> <class '__main__.C'>
- del c.x
- # delete~
- # self -> <__main__.D object at 0x0000026F6A728FA0>
- # instance -> <__main__.C object at 0x0000026F6A728F70>
- # self参数对应的是描述符这个类的实例对象<__main__.D object at 0x0000026F6A728FA0>
- # instance对应的是被描述符拦截的属性所在的类的实例对象<__main__.C object at 0x0000026F6A728F70>
- # owner参数对应被描述符拦截的属性所在的类<class '__main__.C'>
- # 将案例修改为描述符的实现方式
- ######################案例##########################
- # class C:
- # def __init__(self):
- # self._x = 250
- # def getx(self):
- # return self._x
- # def setx(self, value):
- # self._x = value
- # def delx(self):
- # del self._x
- # x = property(getx, setx, delx)
- #
- # c = C()
- # print(c.x)#250
- # c.x = 520
- # print(c.x)#520
- # del c.x
- # print(c.__dict__)#{}
- #########################################################
- class D:
- def __get__(self, instance, owner):
- return instance._x
- def __set__(self, instance, value):
- instance._x = value
- def __delete__(self, instance):
- del instance._x
- class C:
- def __init__(self, x=250):
- self._x = x
- x = D()
- c = C()
- print(c.x)#250
- c.x = 520
- print(c.x)#520
- del c.x
- print(c.__dict__)#{}
- # 代码虽然能实现但不是一段健康的代码,类D中使用了类C中的属性_x
- # property()的原理
- class PropertyL:
- def __init__(self, fget=None, fset=None, fdel=None):
- self.fget = fget
- self.fset = fset
- self.fdel = fdel
- def __get__(self, instance, owner):
- return self.fget(instance)
- def __set__(self, instance, value):
- self.fset(instance, value)
- def __delete__(self, instance):
- self.fdel(instance)
- class C:
- def __init__(self):
- self._x = 250
- def getx(self):
- return self._x
- def setx(self, value):
- self._x = value
- def delx(self):
- del self._x
- p = PropertyL(getx, setx, delx)
- c = C()
- print(c.p)#250
- c.p = 520
- print(c.p)#520
- del c.p
- print(c.__dict__)#{}
- #实现getter()、setter()、deleter()方法
- class PropertyL:
- def __init__(self, fget=None, fset=None, fdel=None):
- self.fget = fget
- self.fset = fset
- self.fdel = fdel
- def __get__(self, instance, owner):
- return self.fget(instance)
- def __set__(self, instance, value):
- self.fset(instance, value)
- def __delete__(self, instance):
- self.fdel(instance)
- def getter(self, func):
- self.fget = func
- return self
- def setter(self, func):
- self.fset = func
- return self
- def deleter(self, func):
- self.fdel = func
- return self
- class D:
- def __init__(self):
- self._x = 250
- @PropertyL
- def x(self):
- return self._x
- @x.setter
- def x(self, value):
- self._x = value
- @x.deleter
- def x(self):
- del self._x
- d = D()
- print(d.x)# 250
- d.x = 520
- print(d.__dict__)# {'_x': 520}
- del d.x
- print(d.__dict__)# {}
- #另一种写法
- class E:
- def __init__(self):
- self._x = 250
- x = PropertyL()
- @x.getter
- def x(self):
- return self._x
- @x.setter
- def x(self, value):
- self._x = value
- @x.deleter
- def x(self):
- del self._x
- e = E()
- print(e.x)# 250
- e.x = 520
- print(e.__dict__)# {'_x': 520}
- del e.x
- print(e.__dict__)# {}
复制代码 |
|