为什么 __getattr__catching 也是存在的属性?

Why is __getattr__catching also existing attributes?

我创建这个 class 是为了测试一些 __getattr__ 功能:

class Trace:
    def __init__(self, val):
        self.val = val

    def __setattr__(self, attr, value):
        print('set ' + attr)

    def __getattr__(self, attr):
        print('get ' + attr)

然后我创建了一个实例

a = Trace(10)
print(a.val)
a.val = 5
print(a.val)

但是,即使我只获取了现有的属性,这也是输出:

set val
get val
None
set val
get val
None

我正在使用 Python 3.7.

__getattr__ 仅在通常找不到属性时调用,但 __setattr__ 没有这样的限制(这就是为什么没有 __getattribute__ 的等价物)。您覆盖 __setattr__ 以不实际设置实例属性,因此该属性始终缺失并且 __getattr__ 无论如何都会被调用。 (是的,它也适用于 __init__。)

删除 __setattr__ 以快速查看您的预期行为,或重新添加其默认行为:

def __setattr__(self, attr, value):
    print('set ' + attr)
    super().__setattr__(attr, value)