根据 this answer :
setattr(instance, name, value)
is syntactic sugar forinstance.__setattr__(name, value)
但是:
class C:
def __init__(self):
# OK.
super().__setattr__("foo", 123)
# AttributeError: 'super' object has no attribute 'foo'
setattr(super(), "foo", 123)
c = C()
什么给了?他们不应该做同样的事情吗?
最佳答案
您链接到的答案掩盖了一些重要的细节。长话短说,setattr
绕过 super
的魔法,所以它尝试在 super()
上设置属性代理对象本身而不是 self
.
setattr(a, b, c)
不是 a.__setattr__(b, c)
的语法糖. setattr
和常规属性分配都查找 __setattr__
通过直接搜索对象类型的 method resolution order 的方法(类和所有父类(super class)的精心排序的列表),绕过实例字典和 __getattribute__
/__getattr__
钩子(Hook)。
相比之下,a.__setattr__(b, c)
只是对 __setattr__
执行常规属性查找, 所以它经过 __getattribute__
和 __getattr__
,它会检查实例字典,除非 __getattribute__
说不要。
super
实现自定义 __getattribute__
方法来做它的属性魔法。 super().__setattr__
使用这个钩子(Hook),找到 C
的父类(super class)的 __setattr__
和绑定(bind)self
, 从而产生一个方法对象,用于在 self
上设置属性.
setattr(super(), ...)
绕过 __getattribute__
.它执行前面提到的直接 MRO 搜索,搜索 super
的 MRO,生成一个用于在 super 实例本身 上设置属性的方法对象。 super
实例没有 __dict__
存储任意属性数据,所以尝试设置一个 foo
属性失败并显示 TypeError
.
关于python - 为什么 setattr(super(), ...) 不等同于 super().__setattr__(...)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56144186/