获取描述符对象的简洁方法 [英] Neat way to get descriptor object
问题描述
在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__
东西
Is there better way to do it? I don't like this self.__class__.__dict__
stuff
推荐答案
A.attr
导致Python调用SomeDescriptor().__get__(None, A)
,因此如果SomeDescriptor.__get__
当inst
为None
时返回self
,则
A.attr
causes Python to call SomeDescriptor().__get__(None, A)
so if you have SomeDescriptor.__get__
return self
when inst
is None
, then A.attr
will return the descriptor:
class SomeDescriptor():
def __get__(self, inst, instcls):
if inst is None:
# instance attribute accessed on class, return self
return self
然后您使用来访问描述符
Then you access the descriptor with
desc = type(self).attr
如果仅将属性名称称为字符串attr_name
,则可以使用
If the attribute's name is known only as a string, attr_name
, then you would use
desc = getattr(type(self), attr_name)
即使self
是A
的子类的实例,该功能仍然有效,而
This works even if self
is a instance of a subclass of A
, whereas
desc = self.__class__.__dict__[attr_name]
仅在self
是A
的实例时起作用.
would only work if self
is an instance of 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()
正常工作:
This shows A.attr
returns the descriptor, and a.somewhere()
works as expected:
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:
This shows it works for subclasses of A
too. If you uncomment
desc = self.__class__.__dict__[attr_name]
, you'll see
b.somewhere()
raises a KeyError:
class B(A): pass
b = B()
print(B.attr)
# <__main__.SomeDescriptor object at 0xb7395fcc>
print(b.attr)
# 4
print(b.somewhere())
# True
顺便说一句,即使您不能完全控制SomeDescriptor的定义,您仍然可以将其包装在一个描述符中,当inst
为None时,该描述符返回self
:
By the way, even if you do not have full control over the definition of SomeDescriptor, you can still wrap it in a descriptor which returns self
when inst
is 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']
也遇到同样的问题.
这篇关于获取描述符对象的简洁方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!