Python类成员查找的基础机制

时间:2011-10-12 19:21:46

标签: python dictionary lookup member

在Python中,如果我定义了三个类:

class A:
    name = 'oliver'
    hailstone_ending = [4,2,1]

class B:
    def __init__(self):
        self.name = 'oliver'
        self.hailstone_ending = [4,2,1]

class C:
    pass

c = C()
c.name = 'oliver'
c.hailstone_ending = [4,2,1]

引擎盖下,每个类的成员查找功能是否相同?似乎A只需要在字典上查找所有实例的成员;另一方面,C需要使用存储在每个实例中的字典。如果解释器非常聪明,理论上可以注意到B 的所有实例必须包括成员namehailstone_ending;因此,它可能等同于A

但另一方面,如果在查找类成员的字典上允许del操作,则在所有这些类中查找的机制可能是等效的,因为可用成员将依赖于实例

我感兴趣的是我有一些代码创建了几千个类型C的类,我注意到它非常慢并且内存很耗尽。我最近以不同的方式重写了它,感觉效率更高(但我没有经过严格的测试,因此它可能是相同的。)

非常感谢您的见解!

2 个答案:

答案 0 :(得分:2)

在python中,每个类和每个实例都会获得一个字典。 A使用类字典。类BC的示例正在使用实例字典。 B不等同于A - python不是很快,如果不是不可能证明B的任何实例都不会变异,那将是非常困难的。

证明:

>>> class D:
...   def __init__(self):
...     self.a = 3
... 
>>> d = D()
>>> d.a
3
>>> D.a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: class D has no attribute 'a'
>>> dd = D()
>>> dd.a
3
>>> D.a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: class D has no attribute 'a'

你的问题让我想起了javascript的原型。

另外:如果在实例字典中找不到成员,则成员查找可以回退到类字典上,但写入将使用实例字典。

答案 1 :(得分:2)

  

引擎盖下,每个类的成员查找功能是否相同?

除非覆盖__getattribute__,否则属性查找首先检查对象属性,然后键入属性。它并不关心课程的来源。

  

似乎A只需要在字典上查找所有实例的成员;另一方面,C需要使用存储在每个实例中的字典。如果解释器非常聪明,理论上可以注意到B的所有实例都必须包含成员名称和hailstone_ending;因此,它可能相当于A。

A中,属性存储在A.__dict__中,即存储在类型中。在BC中,属性存储在self.__dict__中,即存储在实例上。在所有情况下都存在两个词典。没有更多的东西。不,BC之间没有区别。