Is __init__ in python a constructor or a method?
Somewhere it says constructor and somewhere it says method, which is quite confusing.
It is correct to call it a method. It is incorrect, or at best inaccurate, to call it a constructor.
Specifically, it is a magic method. They are also called special methods, "dunders", and a few other names.
This particular method is used to define the initialisation behavior of an object. It is not really similar to a constructor, and it is not even the first method to be called on a new instance.
We use __init__ to set up the state of an already-created instance. It will be automatically called when we use the syntax A() to create an instance of a class A, which is why someone might loosely refer to it as a "constructor". But the responsibility of __init__ is not related to instance construction, really the __new__ magic method is more similar to a constructor in that respect.
In addition to the answer by #wim it is worth noting that the object has already been created by the time __init__ is called i.e. __init__ is not a constructor. Furthermore, __init__ methods are optional: you do not have to define one. Finally, an __init__ method is defined first only by convention i.e. it could be defined after any of the other methods.
Related
I'm learning python and the construct method __init__ makes me confused.
class Test(object):
def __init__(self):
pass
As known, python implicitly pass a parameter representing the object itself at the first place. It is acceptable in common member functions. But what makes me confused is that the constructor requests an object itself.
It looks like the c++ code below. This code does not make sense! The parameter thiz does not even exit before the constructor!
class Test {
public:
Test(Test *thiz);
};
So, my question is, why python needs a "non-existent" self object in constructor __init__?
__init__ behaves like any other normal function in a class. It gets called by the interpreter at a special time if it is defined, but there is nothing special about it. You can call it any time yourself, just like a regular method.
Here are some facts to help you see the picture:
Function objects are non-data descriptors in python. That means that function objects have a __get__ method, but not __set__. And if course they have a __call__ method to actually run the function.
When you put a def statement in a class body, it creates a regular function, just like it would elsewhere. You can see this by looking at type(Test.__init__). To call Test.__init__, you would have to manually pass in a self parameter.
The magic happens when you call __init__ on an instance of Test. For example:
a = Test()
a.__init__()
This code actually calls __init__ twice (which we'll get into momentarily). The explicit second call does not pass in a parameter to the method. That's because a.__init__ has special meaning when the name __init__ is present in the class but not the instance. If __init__ is a descriptor, the interpreter will not return it directly, but rather will call __get__ on it and return the result. This is called binding.
a.__init__() is roughly equivalent to type(a).__init__.__get__(a, None)(). The call .__get__(a, None) returns a callable object that is a bound method. It is like a special type of partial function, in which the first positional parameter is set to a. You can see this by checking type(a.__init__).
The self parameter is passed to methods as the first positional parameter. As such, it does not have to be called self. The name is just a convention. def __init__(this): or def __init__(x) would work just as well.
Finally, let's discuss how a = Test() ends up calling __init__. Class objects are callable in python. They have a class themselves, called a metaclass (usually just type), which actually defines a __call__ method. When you do Test(), you are literally calling the class.
By default, the __call__ method of a class looks something (very roughly approximately) like this:
def __call__(cls, *args, **kwargs):
self = cls.__new__(cls, *args, **kwargs)
if isinstance(self, cls):
type(self).__init__(self, *args, **kwargs)
So a new instance is only created by __new__, not __init__. The latter is an initializer, not a constructor or allocator. In fact, as I mentioned before, you can call __init__ as often as you like on most classes. Notable exceptions include immutable built-in classes like tuple and int.
As an initializer, __init__ obviously needs access to the object it is initializing. Your example does nothing with self, but it is pretty standard to set instance attributes and do something things to prep the object. For cases like yours, an explicit __init__ is not necessary at all, since a missing function will be found in the base class hierarchy.
This question already has answers here:
What is the purpose of the `self` parameter? Why is it needed?
(26 answers)
Closed 6 months ago.
Are you supposed to use self when referencing a member function in Python (within the same module)?
More generally, I was wondering when it is required to use self, not just for methods but for variables as well.
Adding an answer because Oskarbi's isn't explicit.
You use self when:
Defining an instance method. It is passed automatically as the first parameter when you call a method on an instance, and it is the instance on which the method was called.
Referencing a class or instance attribute from inside an instance method. Use it when you want to call a method or access a name (variable) on the instance the method was called on, from inside that method.
You don't use self when
You call an instance method normally. Using Oskarbi's example, if you do instance = MyClass(), you call MyClass.my_method as instance.my_method(some_var) not as instance.my_method(self, some_var).
You reference a class attribute from outside an instance method but inside the class definition.
You're inside a staticmethod.
These don'ts are just examples of when not to use self. The dos are when you should use it.
Use self to refer to instance variables and methods from other instance methods. Also put self as the first parameter in the definition of instance methods.
An example:
class MyClass(object):
my_var = None
def my_method(self, my_var):
self.my_var = my_var
self.my_other_method()
def my_other_method(self):
# do something...
There is nothing 'special' about the name self. It is the name preferred by convention by Pythonistas, to indicate what that parameter is expected to contain.
The Python runtime will pass a 'self' value when you call an instance method on an instance, whether you deliberately provide for it or not. This will usually result in an easily diagnosed/understood error (since the function will get called with the wrong number of parameters), but the use of *args can lead to rather more strange type errors.
The parameter is passed implicitly when you call an instance method on an instance. It contains the instance upon which you call the method. So you don't mention self in the function call because (a) as noted above, that wouldn't make any sense (there isn't a self in scope, in general, and self is not a keyword or special name or anything); (b) you've already indicated the instance to use (by writing my_instance.).
You can, of course, explicitly call an instance method by accessing it from the class. In this case, you'll need to pass the instance explicitly as the first parameter. You generally speaking don't want to do this. And you especially don't want to write code that considers the possibility that the first parameter is something else that's been explicitly passed in this way. This is akin to checking if (this == null) in C++: you don't do it, because if it could possibly mean anything, then the calling code is wrong, morally if not legally. (At least in Python you won't have problems with undefined behaviour, but it's still morally wrong.)
Within the instance method, since self is a parameter which has been assigned the instance as a value, you can write self.whatever to access attributes of the instance. Unlike in some other 'implicit this' style languages, the attribute names are not implicitly "in scope".
There are no other use cases for self, since again it's not a special name, and that is the one specific purpose that the naming convention addresses. If you needed to access a 'variable' (really an attribute) from another module, you would use the module name. If you wanted to access one from the current module, no prefix is needed, or really possible for that matter. (Well, you could explicitly look it up in the dict returned by globals(), but please don't do that.)
For instance variable and for methods it is mandatory to use self anytime.
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.
Generally speaking, I would tally this one up to the Zen of Python -- specifically, the following statements:
Explicit is better than implicit.
Readability counts.
In the face of ambiguity, refuse the temptation to guess.
... and so on.
It's the mantra of Python -- this, along with many other cases may seem redundant and overly simplistic, but being explicit is one of Python's key "goals." Perhaps another user can give more explicit examples, but in this case, I would say it makes sense to not have arguments be explicitly defined in one call, then vanish -- it might make things unclear when looking at a child function without also looking at its parent.
Let's say I have classes Base(object) and Derived(Base). These both implement a function foo, with Derived.foo overriding the version in Base.
However, in one of the methods, say Base.learn_to_foo, I want to call Base.foo instead of the derived version regardless of whether it was overridden. So, I call Base.foo(self) in that method:
class Base(object):
# ...
def learn_to_foo(self, x):
y = Base.foo(self, x)
# check if we foo'd correctly, do interesting stuff
This approach seems to work and from a domain standpoint, it makes perfect sense, but somehow it smells a bit fishy. Is this the way to go, or should I refactor?
The answer is NOT to use the super() function. The way you are doing is exactly right as you don't want to invoke the virtual method that is overridden in the super class. Since you seem to want the base class' exact implementation all the time, the only way is to get the base class' unbound method object back, bound it to self, which could be an instance of Base or Derived. Invoke the unbound method with self supplied explicitly as the first parameter gives you back a bound method. From this point forward, Base.foo will be acting on the instance self's data. This is perfectly acceptable and is the way Python deals with non-virtual method invocation. This is one of the nice things that Python allows you to do that Java does not.
It is recommended:
def learn_to_foo(self, x):
super(Derived, self).foo(x)
More information at http://docs.python.org/library/functions.html#super
An alternative is to use the 'super' built-in:
super(Derived, self).foo(x) # Python 2
super().foo(x) # Python 3
The __init__() function gets called when object is created.
Is it ok to call an object __init__() function again, after its been created?
instance = cls(p1=1, p2=2)
# some code
instance.__init__(p1=123, p2=234)
# some more code
instance.__init__(p1=23, p2=24)
why would anyone wanna call __init__() on an object that is already created?
good question. i wanna re-initialize the instance's fields.
It's fine to call __init__ more than once on an object, as long as __init__ is coded with the effect you want to obtain (whatever that may be). A typical case where it happens (so you'd better code __init__ appropriately!-) is when your class's __new__ method returns an instance of the class: that does cause __init__ to be called on the returned instance (for what might be the second, or twentieth, time, if you keep "recycling" instances via your __new__!-).
You can, but it's kind of breaking what __init__ is intended to do. A lot of Python is really just convention, so you might as well follow then and expect __init__ to only be called once. I'd recommend creating a function called init or reset or something which sets the instance variables, use that when you want to reset the instance, and have __init__ just call init. This definitely looks more sane:
x = Pt(1,2)
x.set(3,4)
x.set(5,10)
As far as I know, it does not cause any problems (edit: as suggested by the kosher usage of super(...).__init__(...)), but I think having a reset() method and calling it both in __init__() and when you need to reset would be cleaner.