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

2024-04-29 11:54:28 发布

您现在位置:Python中文网/ 问答频道 /正文

在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将用MyClassfake参数调用__getattr__

MyClass().fake将使用MyClass实例和fake参数调用__getattr__

如果我只在mixin上实现__getattr__逻辑,而不使用self参数,那就没问题了。

如果与MyClass(object): field = 1方法相比,__getattr__定义的MyClass.fieldMyClass().fieldfield值解析工作不同,我可以编写更漂亮的按类和实例的自定义值解析吗?因为当我想要得到field时,首先在实例中搜索,然后在类中搜索,但是我不明白__getattr__为什么会以另一种方式工作。

类似的问题:__getattr__ on a class and not (or as well as) an instanceDifference between accessing an instance attribute and a class attribute


Tags: no代码nameselffieldobjecttypemyclass
1条回答
网友
1楼 · 发布于 2024-04-29 11:54:28

不,如果您必须同时支持类和实例上的任意属性查找,那么您唯一的选择就是在元类和类上实现一个__getattr__钩子方法,每个钩子方法都支持类和实例上的查找。

这是因为特殊的钩子方法总是在类型上查找,所以type(obj).__getattr__。因此,对于MyClass.fake使用元类__getattr__。请参见Special method lookup for new-style classes;我解释了为什么这是在previous answer中。

简短的原因是,在您的例子中,MyClass.fake将转换为MyClass.__getattr__('fake'),然后__getattr__是一个需要两个参数(selfname)的未绑定方法,这将失败。

相关问题 更多 >