在python中获取类和实例的属性

时间:2013-03-13 14:07:17

标签: python class instance metaclass getattr

在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 instanceDifference between accessing an instance attribute and a class attribute

1 个答案:

答案 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),这会失败。