Python 从类或实例设置属性时,查找过程是什么?

Python 从类或实例设置属性时,查找过程是什么?,python,python-3.x,Python,Python 3.x,简而言之,Python描述了 但我不确定何时设置属性: 设置属性 请注意,属性查找步骤仅如刚才所述 引用属性时,而不是绑定属性时。什么时候 绑定(在类或实例上)名称为的属性 不特殊(除非a\uuuuuu setattr\uuuuu方法,或该\uuuu设置 重写描述符的方法,截取 实例属性),您只影响 属性(分别在类或实例中)。换句话说,, 对于属性绑定,不涉及任何查找过程,除了 用于检查覆盖描述符的 我的问题是: 从类中设置属性(例如cls.name=value)时,“查找”过程是什么 从对象

简而言之,Python描述了

但我不确定何时设置属性:

设置属性

请注意,属性查找步骤仅如刚才所述 引用属性时,而不是绑定属性时。什么时候 绑定(在类或实例上)名称为的属性 不特殊(除非a
\uuuuuu setattr\uuuuu
方法
,或
\uuuu设置
重写描述符的方法
,截取 实例属性),您只影响 属性(分别在类或实例中)。换句话说,, 对于属性绑定,不涉及任何查找过程,除了 用于检查覆盖描述符的

我的问题是:

  • 从类中设置属性(例如
    cls.name=value
    )时,“查找”过程是什么

  • 从对象设置属性(例如,
    obj.name=value
    )时,“查找”过程是什么

这些程序似乎涉及

  • \uuuu setattr\uuuu
    方法

    \uuuuu setattr\uuuuu(自我、姓名、价值)

    每次请求绑定属性
    x.y
    (通常是赋值语句
    x.y=value
    ,但是,例如,
    setattr(x,'y',value)
    ),Python调用
    x.\uuuu setattr\uuuuu('y',值)
    。Python总是调用
    \uuuu setattr\uuuu
    来处理任何 x上的属性绑定—与
    \uuuu getattr\uuuuu
    的一个主要区别是 更接近于
    \uuu getattribute\uuu
    )。为了避免递归,当
    x.\uuuu setattr\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。,
    通过
    x.\uuuuu dict\uuuuuu[name]=value
    );更好的是,
    \uuuuu setattr\uuuu
    可以委托 设置到超类(通过调用
    super(C,x)。\uuuu setattr\uuuu('y',value)
    或者,在v3中,只需
    super()。Python忽略了
    
    \uuuu setattr\uuuu
    的返回值。如果
    \uuuu setattr\uuuu
    不存在(即继承自
    object
    ),并且
    C.y
    不是覆盖描述符,Python通常翻译
    x.y=z
    进入
    x.\uuuu dict\uuuu['y']=z

  • 重写描述符的
    \uuuuuuuuuuuuuuuuuuu
    方法(所以我问)

  • 属性的
    \uuuu dict\uuuu
    条目(分别在类或实例中)
,当从类设置属性和从实例设置属性时,自然会认为“查找”过程是不同的

但是由于在Python3中,每个类对象实际上都是其元类的一个实例(例如,
type
class),因此从类中设置属性的“查找”过程和从实例中设置属性的“查找”过程真的不同吗


谢谢。

对于
x.y=z
,Python会以一种绕过
\uuuu getattr\uuuuuuuu
\uu getattr\uuuuuuu
x
自己的
\uuu dict\uuuuuuuuuuuu
的方式查找
,然后调用
x.\uuuu setattr\uuuuuuuuz('uuy',code>)

自定义的
\uuuu setattr\uuuuuu
可以做任何它想做的事情,但这里是默认设置:

  • 搜索
    类型(x)。\uuu mro\uuuuuuu
    以查找与属性名称匹配的
    条目

  • 如果此搜索使用
    \uuuu set\uuuuu
    方法(查找
    \uuuu set\uuuuu
    与查找
    \uuuu setattr\uuuuuu
    的方法相同)找到描述符
    descr.\uuuu set\uuuuuuuuux,z)

    2.a。在极不寻常的情况下,搜索找到的描述符带有
    \uuuuu delete\uuuuu
    但没有
    \uuuu set\uuuuuu
    ,请引发
    属性错误

  • 否则,设置
    x.\uuuuu dict\uuuu['y']=z
    ,或者如果
    x
    没有
    \uuuuu dict\uuu
    ,则引发
    属性错误。(这使用了“真实的”
    \uuuu dict\uuuuu
    ,绕过了
    映射代理等功能)


  • 这适用于类型和其他对象,但需要注意的是
    type.\uuuu setattr\uuuu
    将拒绝设置用C编写的类的属性,和
    type.\uuuuu setattr\uuuuuu
    执行一些额外的内部维护,您永远不需要担心,除非您执行一些疯狂的、不受支持的操作来绕过它。

    非常简单:它指定给该类的属性。它不涉及基类。这本书中的引用似乎并不简单。@Tim你的问题在第二句引用的最后一句中得到了回答:“换句话说,对于属性绑定,除了检查重写描述符之外,没有涉及任何查找过程。”我不确定我是否理解这句话,我认为这个句子不能代替整个段落,因为段落暗示仍然有一些“查找”过程,而且这个句子也遗漏了段落中的
    \uuuu setattr\uuu
    方法@ChristianDean@Tim“您只影响属性的
    \u dict\u
    条目”有什么复杂之处?谢谢。(1) 第一步是否意味着在
    类型(x)中查找一个class属性为
    y
    的类?如果是,并且我们发现一个类可以是
    类型(x)
    的祖先类,为什么在
    descr.\uuu set\uuuuuuuuuuu(x,z)
    的第2步和
    x.\uu dict\uuuuuuuu['y']=z
    的第3步中设置实例属性,而不是设置找到的类的class属性
    y
    ?(2) 当步骤1中的搜索未找到任何类时,或者当步骤1中的搜索找到某个类但在步骤2中找到的属性不是描述符时,是否会发生步骤3?(3)如果可以为每种情况添加一些示例,则会发生这种情况