整洁的方式来获得描述符对象
问题描述:
在Python 3整洁的方式来获得描述符对象
class A(object):
attr = SomeDescriptor()
...
def somewhere(self):
# need to check is type of self.attr is SomeDescriptor()
desc = self.__class__.__dict__[attr_name]
return isinstance(desc, SomeDescriptor)
有没有更好的方式来做到这一点?我不喜欢这个self.__class__.__dict__
东西
答
A.attr
导致Python来调用SomeDescriptor().__get__(None, A)
所以如果你有SomeDescriptor.__get__
返回self
时inst
为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
是无:
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']
从相同问题的困扰。
答
是的,要访问类的描述符,阻止descriptor.__get__
被调用的唯一方法是通过类__dict__
。
你可以使用type(self)
访问当前类,并vars()
访问__dict__
更符合API-方式:
desc = vars(type(self))['attr']
如果您的描述是完全自定义的,你总是可以从SomeDescriptor.__get__()
返回self
如果实例参数是None
,这是在您直接在类上访问描述符时发生的。您可以删除vars()
电话,直奔:
desc = type(self).attr
的property()
描述对象正是这样做的。
'type(self).__ dict __ ['attr']''怎么样? –