关于__getattr__和__getattribute__的一些问题?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于__getattr__和__getattribute__的一些问题?相关的知识,希望对你有一定的参考价值。

第一个演示:

class B:
    def __init__(self):
        self.name = '234'
    # def __getattribute__(self, name):
    #     print('getattr')
    def __getattr__(self, name):    
        print('get')
    def __setattr__(self, name, value):
        print('set')
    def __delattr__(self, name):
        print('del')


b = B()
print(b.__dict__)
b.name

b.__dict__{},但第二个演示:

class B:
    def __init__(self):
        self.name = '234'
    def __getattribute__(self, name):
        print('getattr')
    def __getattr__(self, name):
        print('get')
    def __setattr__(self, name, value):
        print('set')
    def __delattr__(self, name):
        print('del')


b = B()
print(b.__dict__)
b.name

b.__dict__None,为什么?而b.__dict__调用__getattribute__,但不要援引__getattr__,这是否意味着__getattribute__将阻止援引__getattr__

答案

调用__getattribute____setattr____delattr__方法进行所有属性访问(获取,设置和删除)。另一方面,__getattr__仅被称为缺失属性;它通常不会被实现,但如果是,那么__getattribute__会调用它,如果它无法找到该属性,或者AttributeError引发了__getattribute__

您使用除了打印和返回None之外什么都不做的方法替换了3个主要方法的标准实现(默认情况下没有显式的return语句)。 __dict__只是另一个属性访问,你的__getattribute__方法返回None,从来没有自己调用__getattr__或引发AttributeError

来自Customizing attribute access documentation

object.__getattr__(self, name) 当属性查找未在通常位置找到属性时调用(即,它不是实例属性,也不在self的类树中找到)。

object.__getattribute__(self, name) 无条件调用以实现类的实例的属性访问。如果该类还定义了__getattr__(),则除非__getattribute__()明确地调用它或引发AttributeError,否则不会调用后者。

(大胆强调我的)。

要么调用基本实现(通过super().__getattribute__),要么引发AttributeError

>>> class B:
...     def __init__(self):
...         self.name = '234'
...     def __getattribute__(self, name):
...         print('getattr')
...         return super().__getattribute__(name)
...     def __getattr__(self, name):
...         print('get')
...     def __setattr__(self, name, value):
...         print('set')
...     def __delattr__(self, name):
...         print('del')
...
>>> b = B()
set
>>> b.__dict__
getattr
{}
>>> b.name
getattr
get
>>> class B:
...     def __init__(self):
...         self.name = '234'
...     def __getattribute__(self, name):
...         print('getattr')
...         raise AttributeError(name)
...     def __getattr__(self, name):
...         print('get')
...     def __setattr__(self, name, value):
...         print('set')
...     def __delattr__(self, name):
...         print('del')
...
>>> b = B()
set
>>> b.__dict__
getattr
get
>>> b.name
getattr
get

请注意,通过调用super().__getattribute__,可以找到实际的__dict__属性。通过提高AttributeError__getattr__被召唤,也返回None

以上是关于关于__getattr__和__getattribute__的一些问题?的主要内容,如果未能解决你的问题,请参考以下文章

Python的__getattr__和__getattribute__

python中__getattr__和__getattribute__区别

__setattr__和__delattr__和__getattr__

`__getattribute__` 和 `__getattr__` 中的错误处理

访问全局变量时模块的 __setattr__ 和 __getattr__

__getattr__和__setattt__使用