【问题标题】:Some questions about __getattr__ and __getattribute__?关于 __getattr__ 和 __getattribute__ 的一些问题?
【发布时间】:2017-12-17 13:29:33
【问题描述】:

第一个演示:

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__

【问题讨论】:

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


    【解决方案1】:

    所有属性访问(获取、设置和删除)都会调用__getattribute____setattr____delattr__ 方法。另一方面,__getattr__ 仅在缺少属性时调用;它通常尚未实现,但如果是,则 __getattribute__ 调用它,如果它无法以其他方式找到该属性,或者如果 AttributeError__getattribute__ 引发。

    您将 3 个主要方法的标准实现替换为仅打印并返回 None 的方法(在没有显式 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

    【讨论】:

    • b.name也不叫__getattr__,但是b没有属性name,那为什么不叫__getattr__呢?
    • @gaussclb: b.name 确实 打电话给__getattribute__; get 已打印。
    • 打印的是getattr而不是get,为什么不调用__getattr__
    • 啊,你的第二个例子。你的 __getattribute__ 替换了内置版本,所以没有任何东西在调用 __getattr__
    • @gaussclb: 但事实并非如此,因为那是__getattribute__ 的责任。您的实现没有调用它
    猜你喜欢
    • 1970-01-01
    • 2020-01-04
    • 2017-12-12
    • 2011-05-16
    • 1970-01-01
    • 2014-11-06
    • 1970-01-01
    • 2019-09-02
    • 2011-01-12
    相关资源
    最近更新 更多