I am wondering how self works under-the-hood in Python classes.
My current limited understanding is that when a class is defined, e.g.
class Foo:
def __init__(self, x: int):
self.x = x
def bar(self, a: float):
print(self.x)
print(a)
we get Foo in the current environment, and this object contains the methods attached to the class definition, in this case bar.
When we create an instance, e.g.
foo = Foo(1)
We now have both foo and Foo, the former containing the assigned fields, and the latter containing the methods.
So now when I call:
foo.bar(3.14)
a lookup to find bar is performed, first in foo.__dict__, and then, failing that, in Foo.__dict__.
Once bar is found in Foo.__dict__, it is called roughly like:
Foo.__dict__["bar"](foo, 3.14)
Is this an accurate explanation of what happens?
And if so, how is foo actually passed to the method? Is it a via a pointer to the instance?
I am a bit confused about how PyObject and PyTypeObject fit into this.
selfis not a keyword in python. It is just a naming convention. You could replace all occurrences ofselfin your code bymeMyselfortargetInstance, and it would work the same.