在python工作中的下一个代码:
class MyClass(object):
field = 1
>>> MyClass.field
1
>>> MyClass().field
1
当我想要自定义字段的返回值时,我使用下一个代码:
class MyClass(object):
def __getattr__(self, name):
if name.startswith('fake'):
return name
raise AttributeError("%r object has no attribute %r" %
(type(self).__name__, name))
>>> MyClass().fake
fake
可是:
>>> MyClass.fake
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: class MyClass has no attribute 'fake'
好的,对于类我可以使用下一个代码:
class MyClassMeta(type):
def __getattr__(cls, name):
if name.startswith('fake'):
return name
raise AttributeError("%r object has no attribute %r" %
(type(self).__name__, name))
class MyClass(object):
__metaclass__ = MyClassMeta
>>> MyClass.fake
fake
可是:
>>> MyClass().fake
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'MyClass' object has no attribute 'fake'
要解决此问题,请使用下一代码:
class FakeAttrMixin():
def __getattr__(self, name):
if name.startswith('fake'):
return name
raise AttributeError("%r object has no attribute %r" %
(type(self).__name__, name))
class MyClassMeta(type, FakeAttrMixin):
pass
class MyClass(object, FakeAttrMixin):
__metaclass__ = MyClassMeta
>>> MyClass.fake
fake
>>> MyClass().fake
fake
MyClass.fake
会使用__getattr__
和MyClass
个参数致电fake
。
MyClass().fake
会使用__getattr__
个实例和MyClass
个参数调用fake
。
如果我只在我的mixin上实现__getattr__
逻辑并且不使用self
参数,那就没关系。
我是否可以按类编写自定义值解析,实例更漂亮,如果field
MyClass.field
MyClass().field
MyClass(object): field = 1
__getattr__
与[{1}}定义的解析效果与field
相比有效1}}方法?因为我想首先在实例中搜索__getattr__
,然后在课堂上搜索,但我无法理解为什么{{1}}以另一种方式工作。
类似问题:__getattr__ on a class and not (or as well as) an instance和Difference between accessing an instance attribute and a class attribute。
答案 0 :(得分:3)
不,如果你必须同时支持类和实例的任意属性查找,那么你唯一的选择是在元类和类上实现一个__getattr__
钩子方法,每个都支持一个查找类和实例。
这是因为特殊的钩子方法总是在类型上查找,所以type(obj).__getattr__
。因此,对于MyClass.fake
,使用了元类__getattr__
。见Special method lookup for new-style classes;我解释了为什么这是previous answer。
简短的原因是,在您的情况下,MyClass.fake
会转换为MyClass.__getattr__('fake')
而__getattr__
则是未绑定的方法,期待两个参数({{1 }}和self
),这会失败。