在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
的所有实例必须包括成员name
和hailstone_ending
;因此,它可能等同于A
。
但另一方面,如果在查找类成员的字典上允许del
操作,则在所有这些类中查找的机制可能是等效的,因为可用成员将依赖于实例
我感兴趣的是我有一些代码创建了几千个类型C
的类,我注意到它非常慢并且内存很耗尽。我最近以不同的方式重写了它,感觉效率更高(但我没有经过严格的测试,因此它可能是相同的。)
非常感谢您的见解!
答案 0 :(得分:2)
在python中,每个类和每个实例都会获得一个字典。 A
使用类字典。类B
和C
的示例正在使用实例字典。 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__
中,即存储在类型中。在B
和C
中,属性存储在self.__dict__
中,即存储在实例上。在所有情况下都存在两个词典。没有更多的东西。不,B
和C
之间没有区别。