I know what data mangling in Python is in general and what its purpose is, but there is one subtle aspect I would like to clarify.
Let's say we have a class:
class P:
def __init__(self):
self.x = 10
self.__y = 20
def get_y(self):
return self.__y
p = P(); p.__dict__
now has the key _P__y
so this is where the data mangling occurred.
My question is, though, how do we access the attribute inside get_y
given that there is no __y
key in __dict__
?
I have a faint guess that there is some magic going on in __getattribute__
and then, after getting AttributeError
, in __getattr__
.
This confusion makes me think that I don't have a 100% understanding of what __init__
does under the hood.
Name mangling is performed by the compiler, not at runtime. Specifically, in CPython, all the generated byte code assumes that the name of the attribute is _P__y
, whenever __y
occurs as an attribute in the class
statement or a function defined inside the class
statement.
>>> import dis
>>> dis.dis(P)
Disassembly of __init__:
3 0 LOAD_CONST 1 (10)
2 LOAD_FAST 0 (self)
4 STORE_ATTR 0 (x)
4 6 LOAD_CONST 2 (20)
8 LOAD_FAST 0 (self)
10 STORE_ATTR 1 (_P__y)
12 LOAD_CONST 0 (None)
14 RETURN_VALUE
Disassembly of get_y:
7 0 LOAD_FAST 0 (self)
2 LOAD_ATTR 0 (_P__y)
4 RETURN_VALUE