Ant*_*luk 8 python descriptor python-3.x python-descriptors
在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)
Run Code Online (Sandbox Code Playgroud)
有更好的方法吗?我不喜欢这个self.__class__.__dict__东西
unu*_*tbu 14
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
Run Code Online (Sandbox Code Playgroud)
然后使用.访问描述符
desc = type(self).attr
Run Code Online (Sandbox Code Playgroud)
如果属性的名称仅作为字符串知道attr_name,那么您将使用
desc = getattr(type(self), attr_name)
Run Code Online (Sandbox Code Playgroud)
这个工程即使self是一个实例子类的A,而
desc = self.__class__.__dict__[attr_name]
Run Code Online (Sandbox Code Playgroud)
只有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)
Run Code Online (Sandbox Code Playgroud)
这显示A.attr返回描述符,并按a.somewhere()预期工作:
a = A()
print(A.attr)
# <__main__.SomeDescriptor object at 0xb7395fcc>
print(a.attr)
# 4
print(a.somewhere())
# True
Run Code Online (Sandbox Code Playgroud)
这表明它也适用于子类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
Run Code Online (Sandbox Code Playgroud)
顺便说一句,即使你没有完全控制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)
Run Code Online (Sandbox Code Playgroud)
所以没有必要使用
desc = self.__class__.__dict__[attr_name]
Run Code Online (Sandbox Code Playgroud)
要么
desc = vars(type(self))['attr']
Run Code Online (Sandbox Code Playgroud)
它遇到了同样的问题.
是的,要访问类的描述符,防止descriptor.__get__被调用的唯一方法是通过类__dict__.
您可以使用type(self)访问当前类,并vars()以__dict__更多符合API的方式访问:
desc = vars(type(self))['attr']
Run Code Online (Sandbox Code Playgroud)
如果您的描述是完全自定义的,你可以随时返回self从SomeDescriptor.__get__()当实例参数是None,当你直接访问类上的描述符发生.您可以放弃vars()通话直接进入:
desc = type(self).attr
Run Code Online (Sandbox Code Playgroud)
该property()描述符对象正是这样做的.