关于__getattr__和__getattribute__的一些问题?

gau*_*clb 4 python attributes overriding operator-overloading python-3.x

第一个演示:

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

b.__dict__是的None,为什么?并b.__dict__调用__getattribute__,但不调用__getattr__,是否意味着__getattribute__将阻止调用__getattr__

Mar*_*ers 5

__getattribute__,__setattr____delattr__方法被称为对所有属性的访问(获取,设置和删除).__getattr__另一方面,只要求缺少属性 ; 它通常不会被实现,但是如果它__getattribute__不能以其他方式找到属性,或者如果它AttributeError被引发则调用它__getattribute__.

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

Customizing属性访问文档:

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

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

(大胆强调我的).

要么调用基本实现(via 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
Run Code Online (Sandbox Code Playgroud)

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