首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么setattr(超级(),.)相当于超级().__setattr__(.)?

为什么setattr(超级(),.)相当于超级().__setattr__(.)?
EN

Stack Overflow用户
提问于 2019-05-15 07:53:59
回答 1查看 1.7K关注 0票数 8

根据这个答案

setattr(instance, name, value)instance.__setattr__(name, value)的语法糖

但是:

代码语言:javascript
复制
class C:
    def __init__(self):
        # OK.
        super().__setattr__("foo", 123)

        # AttributeError: 'super' object has no attribute 'foo'
        setattr(super(), "foo", 123)

c = C()

怎么回事?他们不是应该做同一件事吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 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中失败。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56144186

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档