本帖最后由 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__)# {}
|