What is the difference between __init__ and __call__?
The first is used to initialise newly created object, and receives arguments used to do that:
class Foo:
def __init__(self, a, b, c):
# ...
x = Foo(1, 2, 3) # __init__
The second implements function call operator.
class Foo:
def __call__(self, a, b, c):
# ...
x = Foo()
x(1, 2, 3) # __call__
Why do we use __init__ in Python classes?
By what you wrote, you are missing a critical piece of understanding: the difference between a class and an object. __init__
doesn't initialize a class, it initializes an instance of a class or an object. Each dog has colour, but dogs as a class don't. Each dog has four or fewer feet, but the class of dogs doesn't. The class is a concept of an object. When you see Fido and Spot, you recognise their similarity, their doghood. That's the class.
When you say
class Dog:
def __init__(self, legs, colour):
self.legs = legs
self.colour = colour
fido = Dog(4, "brown")
spot = Dog(3, "mostly yellow")
You're saying, Fido is a brown dog with 4 legs while Spot is a bit of a cripple and is mostly yellow. The __init__
function is called a constructor, or initializer, and is automatically called when you create a new instance of a class. Within that function, the newly created object is assigned to the parameter self
. The notation self.legs
is an attribute called legs
of the object in the variable self
. Attributes are kind of like variables, but they describe the state of an object, or particular actions (functions) available to the object.
However, notice that you don't set colour
for the doghood itself - it's an abstract concept. There are attributes that make sense on classes. For instance, population_size
is one such - it doesn't make sense to count the Fido because Fido is always one. It does make sense to count dogs. Let us say there're 200 million dogs in the world. It's the property of the Dog class. Fido has nothing to do with the number 200 million, nor does Spot. It's called a "class attribute", as opposed to "instance attributes" that are colour
or legs
above.
Now, to something less canine and more programming-related. As I write below, class to add things is not sensible - what is it a class of? Classes in Python make up of collections of different data, that behave similarly. Class of dogs consists of Fido and Spot and 199999999998 other animals similar to them, all of them peeing on lampposts. What does the class for adding things consist of? By what data inherent to them do they differ? And what actions do they share?
However, numbers... those are more interesting subjects. Say, Integers. There's a lot of them, a lot more than dogs. I know that Python already has integers, but let's play dumb and "implement" them again (by cheating and using Python's integers).
So, Integers are a class. They have some data (value), and some behaviours ("add me to this other number"). Let's show this:
class MyInteger:
def __init__(self, newvalue):
# imagine self as an index card.
# under the heading of "value", we will write
# the contents of the variable newvalue.
self.value = newvalue
def add(self, other):
# when an integer wants to add itself to another integer,
# we'll take their values and add them together,
# then make a new integer with the result value.
return MyInteger(self.value + other.value)
three = MyInteger(3)
# three now contains an object of class MyInteger
# three.value is now 3
five = MyInteger(5)
# five now contains an object of class MyInteger
# five.value is now 5
eight = three.add(five)
# here, we invoked the three's behaviour of adding another integer
# now, eight.value is three.value + five.value = 3 + 5 = 8
print eight.value
# ==> 8
This is a bit fragile (we're assuming other
will be a MyInteger), but we'll ignore now. In real code, we wouldn't; we'd test it to make sure, and maybe even coerce it ("you're not an integer? by golly, you have 10 nanoseconds to become one! 9... 8....")
We could even define fractions. Fractions also know how to add themselves.
class MyFraction:
def __init__(self, newnumerator, newdenominator):
self.numerator = newnumerator
self.denominator = newdenominator
# because every fraction is described by these two things
def add(self, other):
newdenominator = self.denominator * other.denominator
newnumerator = self.numerator * other.denominator + self.denominator * other.numerator
return MyFraction(newnumerator, newdenominator)
There's even more fractions than integers (not really, but computers don't know that). Let's make two:
half = MyFraction(1, 2)
third = MyFraction(1, 3)
five_sixths = half.add(third)
print five_sixths.numerator
# ==> 5
print five_sixths.denominator
# ==> 6
You're not actually declaring anything here. Attributes are like a new kind of variable. Normal variables only have one value. Let us say you write colour = "grey"
. You can't have another variable named colour
that is "fuchsia"
- not in the same place in the code.
Arrays solve that to a degree. If you say colour = ["grey", "fuchsia"]
, you have stacked two colours into the variable, but you distinguish them by their position (0, or 1, in this case).
Attributes are variables that are bound to an object. Like with arrays, we can have plenty colour
variables, on different dogs. So, fido.colour
is one variable, but spot.colour
is another. The first one is bound to the object within the variable fido
; the second, spot
. Now, when you call Dog(4, "brown")
, or three.add(five)
, there will always be an invisible parameter, which will be assigned to the dangling extra one at the front of the parameter list. It is conventionally called self
, and will get the value of the object in front of the dot. Thus, within the Dog's __init__
(constructor), self
will be whatever the new Dog will turn out to be; within MyInteger
's add
, self
will be bound to the object in the variable three
. Thus, three.value
will be the same variable outside the add
, as self.value
within the add
.
If I say the_mangy_one = fido
, I will start referring to the object known as fido
with yet another name. From now on, fido.colour
is exactly the same variable as the_mangy_one.colour
.
So, the things inside the __init__
. You can think of them as noting things into the Dog's birth certificate. colour
by itself is a random variable, could contain anything. fido.colour
or self.colour
is like a form field on the Dog's identity sheet; and __init__
is the clerk filling it out for the first time.
Any clearer?
EDIT: Expanding on the comment below:
You mean a list of objects, don't you?
First of all, fido
is actually not an object. It is a variable, which is currently containing an object, just like when you say x = 5
, x
is a variable currently containing the number five. If you later change your mind, you can do fido = Cat(4, "pleasing")
(as long as you've created a class Cat
), and fido
would from then on "contain" a cat object. If you do fido = x
, it will then contain the number five, and not an animal object at all.
A class by itself doesn't know its instances unless you specifically write code to keep track of them. For instance:
class Cat:
census = [] #define census array
def __init__(self, legs, colour):
self.colour = colour
self.legs = legs
Cat.census.append(self)
Here, census
is a class-level attribute of Cat
class.
fluffy = Cat(4, "white")
spark = Cat(4, "fiery")
Cat.census
# ==> [<__main__.Cat instance at 0x108982cb0>, <__main__.Cat instance at 0x108982e18>]
# or something like that
Note that you won't get [fluffy, sparky]
. Those are just variable names. If you want cats themselves to have names, you have to make a separate attribute for the name, and then override the __str__
method to return this name. This method's (i.e. class-bound function, just like add
or __init__
) purpose is to describe how to convert the object to a string, like when you print it out.
Understanding Python super() with __init__() methods
super()
lets you avoid referring to the base class explicitly, which can be nice. But the main advantage comes with multiple inheritance, where all sorts of fun stuff can happen. See the standard docs on super if you haven't already.
Note that the syntax changed in Python 3.0: you can just say super().__init__()
instead of super(ChildB, self).__init__()
which IMO is quite a bit nicer. The standard docs also refer to a guide to using super()
which is quite explanatory.
Is it necessary to include __init__ as the first function every time in a class in Python?
No, it isn't necessary.
For example.
class A(object):
def f():
print 'foo'
And you can of course use it, in this manner:
a = A()
a.f()
In fact you can even define a class in this manner.
class A:
pass
However, defining __init__
is a common practice because instances of a class usually store some sort of state information or data and the methods of the class offer a way to manipulate or do something with that state information or data. __init__
allows us to initialize this state information or data while creating an instance of the class.
Here is a complete example.
class BankAccount(object):
def __init__(self, deposit):
self.amount = deposit
def withdraw(self, amount):
self.amount -= amount
def deposit(self, amount):
self.amount += amount
def balance(self):
return self.amount
# Let me create an instance of 'BankAccount' class with the initial
# balance as $2000.
myAccount = BankAccount(2000)
# Let me check if the balance is right.
print myAccount.balance()
# Let me deposit my salary
myAccount.deposit(10000)
# Let me withdraw some money to buy dinner.
myAccount.withdraw(15)
# What's the balance left?
print myAccount.balance()
An instance of the class is always passed as the first argument to a method of the class. For example if there is class A
and you have an instance a = A()
, whenever you call a.foo(x, y)
, Python
calls foo(a, x, y)
of class A
automatically. (Note the first argument.) By convention, we name this first argument as self
.
Why is __init__() always called after __new__()?
Use
__new__
when you need to control
the creation of a new instance.
Use
__init__
when you need to control initialization of a new instance.
__new__
is the first step of instance creation. It's called first, and is
responsible for returning a new
instance of your class.
In contrast,
__init__
doesn't return anything; it's only responsible for initializing the
instance after it's been created.In general, you shouldn't need to
override__new__
unless you're
subclassing an immutable type like
str, int, unicode or tuple.
From April 2008 post: When to use __new__
vs. __init__
? on mail.python.org.
You should consider that what you are trying to do is usually done with a Factory and that's the best way to do it. Using __new__
is not a good clean solution so please consider the usage of a factory. Here's a good example: ActiveState Fᴀᴄᴛᴏʀʏ ᴘᴀᴛᴛᴇʀɴ Recipe.
How to return a value from __init__ in Python?
__init__
is required to return None. You cannot (or at least shouldn't) return something else.
Try making whatever you want to return an instance variable (or function).
>>> class Foo:
... def __init__(self):
... return 42
...
>>> foo = Foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __init__() should return None
How to get the current Python class name in __init__ regardless of the class of self?
In Python 3 this is pretty straight forward, we can use the __class__
cell variable to get the current class.
In Python 2 we can achieve something similar by injecting class's name in functions globals scope using a metaclass and later cleaning it up.
from functools import wraps
from types import FunctionType
def decorate(func, class_name):
@wraps(func)
def wrapper(*args, **kwargs):
sentinel = object()
actual_value = func.__globals__.get('__class__', sentinel)
func.__globals__['__class__'] = class_name
try:
result = func(*args, **kwargs)
finally:
if actual_value is sentinel:
del func.__globals__['__class__']
else:
func.__globals__['__class__'] = actual_value
return result
return wrapper
class Meta(type):
def __new__(cls, name, bases, attrs):
for k, v in attrs.items():
if isinstance(v, FunctionType):
attrs[k] = decorate(v, name)
return type.__new__(cls, name, bases, attrs)
class A:
__metaclass__ = Meta
def func(self):
print(__class__)
print('Inside A')
class B(A):
def func(self):
print(__class__)
print('Inside B')
super(B, self).func()
B().func()
Output:
B
Inside B
A
Inside A
To get the __class__
variable as the class object itself we can make few changes:
def decorate(func, cls):
@wraps(func)
def wrapper(*args, **kwargs):
sentinel = object()
actual_value = func.__globals__.get('__class__', sentinel)
func.__globals__['__class__'] = cls
try:
result = func(*args, **kwargs)
finally:
if actual_value is sentinel:
del func.__globals__['__class__']
else:
func.__globals__['__class__'] = actual_value
return result
return wrapper
class Meta(type):
def __new__(cls, name, bases, attrs):
cls = type.__new__(cls, name, bases, attrs)
for k, v in attrs.items():
if isinstance(v, FunctionType):
setattr(cls, k, decorate(v, cls))
return cls
Now output would be:
<class '__main__.B'>
Inside B
<class '__main__.A'>
Inside A
Python Classes without using def __init__(self)
Your code is perfectly fine. You don't have to have an __init__
method.
You can still use __init__
, even with an ABC. All that the ABC meta tests for is if the names have been defined. Setting images
in an __init__
does requires that you define a class attribute, but you can set that to None
at first:
class Servers(BaseMenu):
menu_name = "Servers"
images = None
foo = None
def __init__(self):
self.images = list_images.get_images()
self.foo = list_list.get_list()
Now you can set constraints on the ABC requiring that a images
abstract property be available; the images = None
class attribute will satisfy that constraint.
Related Topics
Swift If Or/And Statement Like Python
How to Release Memory Used by a Pandas Dataframe
Call a Function with Argument List in Python
Why Can't Python Find Shared Objects That Are in Directories in Sys.Path
Separate a Row of Strings into Separate Rows
Is There a Python Equivalent for Rspec to Do Tdd
How to Integrate a Standalone Python Script into a Rails Application
Integration Testing for a Web App
How to Write a Perl, Python, or Ruby Program to Change the Memory of Another Process on Windows
Looking for Recommendation on How to Convert PDF into Structured Format
In Python Can One Implement Mixin Behavior Without Using Inheritance
Restrictons of Python Compared to Ruby: Lambda'S
Efficient Ways to Duplicate Array/List in Python
Renaming a Virtualenv Folder Without Breaking It