Python 类成员查找的底层机制
在 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 类型的类,我注意到它非常慢并且占用内存。我最近用不同的方式重写了它,感觉效率更高(但我没有严格测试它,所以可能是一样的)。
非常感谢您的见解!
In Python, if I define three classes:
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]
Under the hood, does member lookup function in the same way for each class? It seems that A
would only need on dictionary to lookup members for all instances; C
, on the other hand, would need to use a dictionary stored within each of these instances. If the interpreter were very intelligent, it could theoretically notice that all instances of B
must include members name
and hailstone_ending
; therefore, it could be equivalent to A
.
But on the other hand, if the del
operation is permitted on the dictionary that looks up class members, the machinery for lookup in all of these classes may be equivalent, because the available members would be instance-dependent.
My interest is that I had some code that created several thousand classes of type C
and I noticed it was very slow and memory hungry. I rewrote it recently a different way, and it feels more efficient (but I haven't rigorously tested it, and so it may be the same).
Thanks a lot for your insight!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
除非您重写
__getattribute__
,否则属性查找首先检查对象属性,然后键入属性。它并不关心班级是如何形成的。在
A
中,属性存储在A.__dict__
中,即存储在类型上。在B
和C
中,属性存储在self.__dict__
中,即在实例上。两种字典在所有情况下都存在。没有更多的事情了。不,B
和C
之间没有区别。Unless you override
__getattribute__
, the attribute lookup first checks object attributes, then type attributes. It doesn't care how the class came to be.In
A
, attributes are stored inA.__dict__
, i.e. on the type. InB
andC
, attributes are stored in theself.__dict__
, i.e. on the instance. Both dictionaries are present in all cases. There's nothing more to it. And no, there is no difference betweenB
andC
.在Python中,每个类和每个实例都有一个字典。
A
使用类字典。类B
和C
的示例使用实例字典。B
不会等价于A
—— python 的目的并不是要快,要证明没有B< 的实例,即使不是不可能,也会非常困难。 /code> 会发生变异。
证明:
你的问题让我想到了 javascript 的原型。
另外:如果在实例字典中找不到成员,则成员查找可以依靠类字典,但写入将使用实例字典。
In python, each class and each instance gets a dictionary.
A
uses the class dictionary. The examples for classesB
andC
are using the instance dictionaries.B
will not be equivalent toA
-- python is not intended to be fast, it would be very hard if not impossible to prove that no instances ofB
would get mutated.Proof:
Your question makes me think of javascript's prototypes.
Also: member lookup can fall back on the class dictionary, if the member is not found in the instance dictionary, but writing will use the instance dictionary.