在Python中,为什么属性优先于实例属性?

2024-06-08 02:20:57 发布

您现在位置:Python中文网/ 问答频道 /正文

This article描述Python在执行o.a时如何查找对象的属性。优先顺序很有趣,它寻找:

  1. 作为数据描述符的类属性(通常是属性)
  2. 实例属性
  3. 任何其他类属性

我们可以使用下面的代码来确认这一点,它创建了一个具有实例属性a的对象{},该对象的类包含一个同名的属性:

class C:
    def __init__(self):
        self.__dict__['a'] = 1

    @property
    def a(self):
        return 2

o = C()
print(o.a)  # Prints 2

为什么Python使用这个优先级顺序而不是“朴素”顺序(实例属性优先于所有类属性)?Python的优先级顺序有一个明显的缺点:它使属性查找变得更慢,因为Python不只是返回一个o的属性(一个常见的情况),Python必须首先搜索o的类及其所有超类来查找数据描述符。在

Python的优先级顺序有什么好处?这可能不仅仅适用于上述情况,因为拥有一个实例变量和一个同名的属性在很大程度上是一个小问题(注意需要使用self.__dict__['a'] = 1来创建instance属性,因为通常的self.a = 1会调用该属性)。在

“天真”的查找顺序是否会引起问题?在


Tags: 数据对象实例代码self属性顺序init
3条回答

对于旧样式类(PEP 252):

The instance dict overrides the class dict, except for the special attributes (like __dict__ and __class__), which have priority over the instance dict.

重写实例dict中的__dict____class__将破坏属性查找,并导致实例以极其奇怪的方式运行。在

在新样式的类中,Guido选择了以下属性查找实现来保持一致性(PEP 252):

  1. Look in the type dict. If you find a data descriptor, use its get() method to produce the result. This takes care of special attributes like __dict__ and __class__.
  2. Look in the instance dict. If you find anything, that's it. (This takes care of the requirement that normally the instance dict overrides the class dict.)
  3. Look in the type dict again (in reality this uses the saved result from step 1, of course). If you find a descriptor, use its get() method; if you find something else, that's it; if it's not there, raise AttributeError.

总之,__dict____class__属性被实现为属性(数据描述符)。为了保持有效状态,实例dict不能重写__dict__和{}。因此,属性(数据描述符)优先于实例属性。在

Guido van Rossum自己(Python的前BDFL)在2001年python2.2引入新的类时设计了这个特性。推理在PEP 252中讨论。明确提到了对属性查找的影响:

This scheme has one drawback: in what I assume to be the most common case, referencing an instance variable stored in the instance dict, it does two dictionary lookups, whereas the classic scheme did a quick test for attributes starting with two underscores plus a single dictionary lookup.

以及:

A benchmark verifies that in fact this is as fast as classic instance variable lookup, so I'm no longer worried.

What I want to know is, why do data descriptors take priority over instance attributes?

如果没有比普通实例查找优先的方法,那么如何拦截实例属性访问?这些方法本身不能是实例属性,因为那样会破坏它们的用途(我认为至少没有关于它们的其他约定)。在

除了@timgeb的简洁评论,我无法解释任何比官方的Descriptor How To更好的描述符

相关问题 更多 >

    热门问题