python - 为什么 setattr(super(), ...) 不等同于 super().__setattr__(...)?

标签 python python-3.x

根据 this answer :

setattr(instance, name, value) is syntactic sugar for 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()

什么给了?他们不应该做同样的事情吗?

最佳答案

您链接到的答案掩盖了一些重要的细节。长话短说,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/

相关文章:

python - 子进程模块输入换行符

python - 在Python中初始化二维列表提供值之间的链接(相同地址)

python - 组中对象之间的 Pygame 碰撞检测

javascript - 将 Javascript 示例中的暴力 Voronoi 图转换为 Python

Python线程发布

python - 带圆形窗口的局部最大值

python - 我的 scipy.sparse.linalg.eigs 发生了什么?

python - 从下拉选项值 Python BeautifulSoup 中抓取

python-3.x - 警告模块两次打印部分警告

python - 将列表附加到列表时出现意外输出