关于__getattr__和__getattribute__的一些问题?

时间:2017-12-17 13:29:34

标签: python python-3.x attributes operator-overloading override

第一个演示:

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__

1 个答案:

答案 0 :(得分:5)

为所有属性访问(获取,设置和删除)调用__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