为什么Python描述符的__get__方法接受拥有者类作为参数?
为什么在Python的描述符中,__get__
方法要接受第三个参数——拥有者类呢?能给个例子说明一下它的用法吗?
第一个参数(self
)是显而易见的,第二个参数(instances
)在通常的描述符模式中是有意义的(接下来会有例子),但我从来没有见过第三个参数(owner
)的用法。有人能解释一下它的使用场景吗?
为了方便大家理解和回答,这里是我见过的描述符的典型用法:
class Container(object):
class ExampleDescriptor(object):
def __get__(self, instance, owner):
return instance._name
def __set__(self, instance, value):
instance._name = value
managed_attr = ExampleDescriptor()
考虑到instance.__class__
是可以使用的,我能想到的就是显式传递类可能与直接从类访问描述符有关,而不是从实例访问(比如Container.managed_attr
)。即便如此,我还是不太明白在这种情况下__get__
里应该做些什么。
4 个回答
是的,这样做是为了让描述符在访问 Container.managed_attr 时能够看到 Container。你可以返回一些适合具体情况的对象,比如在使用描述符来实现方法时,可以返回一个未绑定的方法。
当从类中访问描述符时,instance
的值会是 None
。如果你没有考虑到这种情况(就像你的示例代码没有考虑到的那样),那么在那时就会出现错误。
那么在这种情况下你应该怎么做呢?做一些合理的事情。😉 如果没有其他更好的办法,你可以参考 property
的做法,当从类中访问时返回描述符本身。
owner
是用来表示当你从类本身访问某个属性时,而不是从类的实例访问。在这种情况下,instance
的值会是 None
。
在你的例子中,如果你尝试像这样运行 print(Container.managed_attr)
,就会失败,因为此时 instance
是 None
,所以 instance._name
会引发一个 AttributeError
错误。
你可以通过检查 instance is None
来改善这种情况,这样在记录日志或抛出更有帮助的错误信息时,可以知道这个描述符属于哪个类,因此需要用到 owner
属性。例如:
def __get__(self, instance, owner):
if instance is None:
# special handling for Customer.managed_attr
else:
return instance._name