根据这个答案
setattr(instance, name, value)是instance.__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()怎么回事?他们不是应该做同一件事吗?
发布于 2019-05-15 08:00:04
你说的答案掩盖了一些重要的细节。长话短说,setattr绕过了super的魔力,因此它尝试在super()代理对象本身而不是在self上设置属性。
setattr(a, b, c)不是a.__setattr__(b, c)的语法糖。setattr和常规属性赋值都通过直接搜索对象类型的方法分解顺序 (类和所有超类的有序列表)来查找__setattr__方法,同时绕过实例dict和__getattribute__/__getattr__挂钩。
相反,a.__setattr__(b, c)只对__setattr__执行常规的属性查找,因此它通过__getattribute__和__getattr__检查实例dict,除非__getattribute__说不这样做。
super实现了一个自定义__getattribute__方法来执行其属性魔术。super().__setattr__使用这个钩子,找到C的超类的__setattr__和绑定self,从而生成一个方法对象,用于在self上设置属性。
setattr(super(), ...)绕过__getattribute__。它执行前面提到的直接MRO搜索,通过super的MRO进行搜索,从而生成一个方法对象,用于设置超级实例本身的属性。super实例没有一个__dict__来存储任意属性数据,因此试图设置foo属性的尝试在TypeError中失败。
https://stackoverflow.com/questions/56144186
复制相似问题