Why it's required to use self keyword as an argument when calling the parent method from the child method?
Let me give an example,
class Account:
def __init__(self,filepath):
self.filepath = filepath
with open(self.filepath,"r") as file:
self.blanace = int(file.read())
def withDraw(self,amount):
self.blanace = self.blanace - amount
self.commit()
def deposite(self,amount):
self.blanace = self.blanace + amount
self.commit()
def commit(self):
with open(self.filepath,"w") as file:
file.write(str(self.blanace))
class Checking(Account):
def __init__(self,filepath):
Account.__init__(sellf,filepath) ######## I'm asking about this line.
Regarding this code,
I understand that self is automatically passed to the class when declaring a new object, so,
I expect when I declare new object, python will set self = the declared object, so now the self keyword will be available in the "'init'" child method, so no need to write it manually again like
Account.__init__(sellf,filepath) ######## I'm asking about this line.
All instance methods are just function
-valued class attributes. If you access the attribute via an instance, some behind-the-scenes "magic" (known as the descriptor protocol) takes care of changing foo.bar()
to type(foo).bar(foo)
. __init__
itself is also just another instance method, albeit one you usually only call explicitly when overriding __init__
in a child.
In your example, you are explicitly invoking the parent class's __init__
method via the class, so you have to pass self
explicitly (self.__init__(filepath)
would result in infinite recursion).
One way to avoid this is to not refer to the parent class explicitly, but to let a proxy determine the "closest" parent for you.
super().__init__(filepath)
There is some magic here: super
with no arguments determines, with some help from the Python implementation, which class it statically occurs in (in this case, Checking
) and passes that, along with self
, as the implicit arguments to super
. In Python 2, you always had to be explicit: super(Checking, self).__init__(filepath)
. (In Python 3, you can still pass argument explicitly, because there are some use cases, though rare, for passing arguments other than the current static class and self
. Most commonly, super(SomeClass)
does not get self
as an implicit second argument, and handles class-level proxying.)
Specifically, the function
class defines a __get__
method; if the result of an attribute lookup defines __get__
, the return value of that method is returned instead of the attribute value itself. In other words,
foo.bar
becomes
foo.__dict__['bar'].__get__(foo, type(foo))
and that return value is an object of type method
. Calling a method
instance simply causes the original function to be called, with its first argument being the instance that __get__
took as its first argument, and its remaining arguments are whatever other arguments were passed to the original method call.