A.attr
导致 Python 调用SomeDescriptor().__get__(None, A)
,所以如果你有SomeDescriptor.__get__
return self
when inst
is None
,那么A.attr
将返回描述符:
class SomeDescriptor():
def __get__(self, inst, instcls):
if inst is None:
# instance attribute accessed on class, return self
return self
然后你访问描述符
desc = type(self).attr
如果属性的名称仅作为字符串已知attr_name
,那么您将使用
desc = getattr(type(self), attr_name)
即使self
是 的子类的实例,这也有效A
,而
desc = self.__class__.__dict__[attr_name]
仅当self
是 的实例时才有效A
。
class SomeDescriptor():
def __get__(self, inst, instcls):
if inst is None:
# instance attribute accessed on class, return self
return self
return 4
class A():
attr = SomeDescriptor()
def somewhere(self):
attr_name = 'attr'
desc = getattr(type(self), attr_name)
# desc = self.__class__.__dict__[attr_name] # b.somewhere() would raise KeyError
return isinstance(desc, SomeDescriptor)
这显示A.attr
返回描述符,并按a.somewhere()
预期工作:
a = A()
print(A.attr)
# <__main__.SomeDescriptor object at 0xb7395fcc>
print(a.attr)
# 4
print(a.somewhere())
# True
这表明它也适用于子类A
。如果你取消注释
desc = self.__class__.__dict__[attr_name]
,你会看到
b.somewhere()
引发 KeyError:
class B(A): pass
b = B()
print(B.attr)
# <__main__.SomeDescriptor object at 0xb7395fcc>
print(b.attr)
# 4
print(b.somewhere())
# True
顺便说一句,即使您无法完全控制 SomeDescriptor 的定义,您仍然可以将其包装在一个描述符中,该描述符self
在inst
为 None 时返回:
def wrapper(Desc):
class Wrapper(Desc):
def __get__(self, inst, instcls):
if inst is None: return self
return super().__get__(inst, instcls)
return Wrapper
class A():
attr = wrapper(SomeDescriptor)()
def somewhere(self):
desc = type(self).attr
# desc = self.__class__.__dict__[attr_name] # b.somewhere() would raise KeyError
return isinstance(desc, SomeDescriptor)
所以没有必要使用
desc = self.__class__.__dict__[attr_name]
或者
desc = vars(type(self))['attr']
遇到同样的问题。