开发者

Underlying mechanism for Python class member lookup

开发者 https://www.devze.com 2023-04-13 02:18 出处:网络
In Python, if I define three classes: class A: name = \'oliver\' hailstone_ending = [4,2,1] class B: def __init__(self):

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!


Under the hood, does member lookup function in the same way for each class?

Unless you override __getattribute__, the attribute lookup first checks object attributes, then type attributes. It doesn't care how the class came to be.

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.

In A, attributes are stored in A.__dict__, i.e. on the type. In B and C, attributes are stored in the self.__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 between B and C.


In python, each class and each instance gets a dictionary. A uses the class dictionary. The examples for classes B and C are using the instance dictionaries. B will not be equivalent to A -- python is not intended to be fast, it would be very hard if not impossible to prove that no instances of B would get mutated.

Proof:

>>> 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'

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号