为什么python descriptor中的__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__
可用,我所能想到的是显式传递类与直接从类而不是实例(ex Container.managed_attr
)访问描述符有关。即使这样,我也不清楚在这种情况下__get__
会做什么。
答案 0 :(得分:9)
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
答案 1 :(得分:2)
从课程中访问描述符时,instance
将为None
。如果您没有考虑到这种情况(因为您的示例代码没有),那么此时将发生错误。
在这种情况下应该做什么?无论什么是明智的。 ;)如果没有别的意义,你可以按照property
的例子,从类中访问时返回描述符本身。
答案 2 :(得分:1)
是的,它被使用,以便描述符可以在访问Container.managed_attr时看到Container。您可以返回一些适合用例的对象,如使用描述符实现方法时的未绑定方法。
答案 3 :(得分:0)
我认为 Python 中 owner
方法的 __get__
参数最著名的应用是 classmethod
decorator。这是一个纯 Python 版本:
import types
class ClassMethod:
"Emulate PyClassMethod_Type() in Objects/funcobject.c."
def __init__(self, f):
self.f = f
def __get__(self, instance, owner=None):
if instance is None and owner is None:
raise TypeError("__get__(None, None) is invalid")
if owner is None:
owner = type(instance)
if hasattr(self.f, "__get__"):
return self.f.__get__(owner)
return types.MethodType(self.f, owner)
多亏了 owner
参数,classmethod
不仅适用于从实例而且还适用于类的属性查找:
class A:
@ClassMethod
def name(cls):
return cls.__name__
A().name() # returns 'A' so attribute lookup from an instance works
A.name() # returns 'A' so attribute lookup from a class works too