代码之家  ›  专栏  ›  技术社区  ›  user200783

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

  •  8
  • user200783  · 技术社区  · 7 年前

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

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

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

    class C:
        def __init__(self):
            self.__dict__['a'] = 1
    
        @property
        def a(self):
            return 2
    
    o = C()
    print(o.a)  # Prints 2
    

    为什么python使用这个优先级顺序而不是“naive”顺序(实例属性优先于所有类属性)?python的优先级顺序有一个显著的缺点:它使属性查找速度变慢,因为它不只是返回 O型 如果它存在(常见情况),python必须首先搜索 O型 以及它所有的超类 对于数据描述符。

    python的优先级顺序有什么好处?这可能不只是针对上述情况,因为拥有一个实例变量和一个同名的属性非常重要(注意需要使用 self.__dict__['a'] = 1 创建实例属性,因为通常 self.a = 1 将调用该属性)。

    是否存在“幼稚”的查找顺序会导致问题的不同情况?

    3 回复  |  直到 7 年前
        1
  •  4
  •   fpbhb    7 年前

    GuidovanRossum自己(Python的前BDFL)在2001年用Python2.2引入了新的风格类时设计了这个特性。推理在 PEP 252 . 明确提到了对属性查找的影响:

    这个方案有一个缺点:在我认为最常见的情况下,引用实例dict中存储的实例变量,它执行两个字典查找,而经典方案则执行一个快速测试,以两个下划线和一个字典查找开头的属性。

    以及:

    一个基准测试验证了这实际上和经典的实例变量查找一样快,所以我不再担心了。

        2
  •  2
  •   Joshua    7 年前

    对于旧式课程( PEP 252 ):

    实例dict重写类dict,除了特殊属性(如 __dict__ __class__ ,优先于实例dict。

    重写 第二节 _类__ 在实例中,dict将中断属性查找,并导致实例以极其奇怪的方式运行。

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

    1. 查找dict类型。如果找到数据描述符,请使用其 get() 产生结果的方法。这需要处理一些特殊的属性,比如 第二节 第二类 .
    2. 看看实例dict。如果你发现了什么,就这样。(这处理了通常实例dict重写类dict的要求。)
    3. 再次查看类型dict(实际上,它使用步骤1中保存的结果)。如果您找到了一个描述符,使用它的get()方法;如果您找到了其他的东西,就是它;如果它不在那里,则引发attributeError。

    总之, 第二节 _类__ 属性被实现为属性(数据描述符)。要保持有效状态,实例dict不能重写 第二节 第二类 .因此,属性(数据描述符)优先于实例属性。

        3
  •  1
  •   Walter Tross    7 年前

    我想知道的是,为什么数据描述符优先于 实例属性?

    如果没有比普通实例查找优先的方法,您希望如何拦截实例属性访问?这些方法不能是实例属性本身,因为这样会破坏它们的目的(我认为,至少没有关于它们的附加约定)。

    除了@timgeb的简明评论之外,我对描述符的任何解释都比不上官方的 Descriptor How To