我试图理解Python中的描述符。我似乎无法理解的是描述符方法中的实例和所有者是什么:
object.__get__(self, instance, owner)
现在我读了documentation说:
owner始终是所有者类,而instance是通过所有者访问属性时访问该属性的实例,或者是None。
不幸的是,我无法理解这意味着什么。业主是否参考了班级本身?类对象?然后传递给它的实例的目的是什么?
业主是否参考了班级本身?
是。
类对象?
这是完全相同的事情。
然后传递给它的实例的目的是什么?
描述符如何访问在其他地方查找的实例?例如,如果你使用内置的property
类型,它可以通过存储访问器函数并回调这些函数来工作。这些函数期望当前实例作为第一个参数(规范地命名为“self”)。如果描述符没有获得当前实例,则显然无法将其传递给访问者。
可以通过以下代码说明关系:
class DescriptorClass:
def __get__(self, instance, owner):
return self, instance, owner
class OwnerClass:
descr = DescriptorClass()
ownerinstance = OwnerClass()
self, instance, owner = ownerinstance.descr
assert self is OwnerClass.__dict__['descr']
assert instance is ownerinstance
assert owner is OwnerClass
self, instance, owner = OwnerClass.descr
assert instance is None
考虑一下
__get__(self, instance, owner):
owner
- 这是指创建描述符对象的类,记住描述符对象是在类级别定义的。
instance
- 这是指你定义描述符对象的类owner
的对象。
将instance
传递给描述符的__get__
方法的目的是确保我们知道并识别您正在访问描述符实例的owner
类的哪个对象。
由于描述符对象是在类级别创建的,因此描述符类本身的简单实现可能导致owner
类的多个对象覆盖描述符实例的值。以下是此类代码的示例
def __get__(self, instance, owner):
return self.data
def __set__(self, instance, data):
if value < 1:
raise Exception("Negative or zero is not allowed")
else:
self.data = value
所以在上面的例子中,data
的值只存储在描述符实例中,如果要创建owner
类的多个对象,并且假设这些对象设置了data
的值,则此代码将产生严重的副作用。
所以为了解决这个问题,你需要将data
的值存储在__dict__
的instance
中,但是如果你在描述符类本身没有访问instance
的话你会怎么做?因此,根据我的经验,这是在描述符类中使用instance
的主要目的。作为解决上述问题并使用instance
的参考,这里是代码
class DataDescriptor(object):
def __init__(self, attribute):
self.default = 100
self.attribute = attribute
def __get__(self, instance, owner):
print('Getting the value of', self.attribute,
'__get__ of Data descriptor invoked')
return instance.__dict__.get(self.attribute, self.default)
def __set__(self, instance, value=200):
if value > 0:
print('__set__ of Data descriptor invoked')
instance.__dict__[self.attribute] = value
else:
sys.exit('Negative value not allowed')