The init method
Related code
class Dog: """Represents a dog. attributes: name: str, age: int, energy: float """ def set_info(self, name, age, energy): self.name = name self.age = age self.energy = energy def print(self): print(f'Name: {self.name}, Age: {self.age}') murki = Dog() murki.set_info("Murki", 2, 50)
Python offers special methods that are triggered during specific actions.
One of the most important is __init__
(two underscore characters, followed by init, and then two more underscores),
which runs automatically when an object is created (Dog()
).
class Dog: def __init__(self): print("Test")
Just like any other method, special methods, like __init__
, have self
as its first parameter, which refers to the object being created.
In the above __init__
method, we printed "Test", and we expecte this string
to be printed once we initialize a Dog
instance.
>>> murki = Dog() Test
In the above example we created a dog (Dog()
), and we saved it to a variable (murki
).
After the execution of this line we see the string Test printed. That means when Dog()
was executed, Python activated Dog
's __init__
method, which printed Test
init
is not used to print anything. We printed Test just to prove
that this method is activated in object creating. This method is typically used to set object attributes
and assign values to them.
An object is characterized by its attributes. It is the attributes that differentiate objects
of different classes, not the class name itself. And creating an object without setting some attributes isn't much
useful. So, most of the time, everytime we create an object (murki = Dog()
)
we immediately set its attributes after its initialization (murki.set_info("Murki", 2, 50)
).
This is where __init__
becomes useful, it allows us to assign attributes and their values
at the moment the instance is created.
class Dog: def __init__(self): self.name = "Murki" self.age = 3 self.energy = 50 murki = Dog() print(murki.name, murki.age, murki.energy)
Murki 3 50 >>>
Outside the class, we refer to the dog using the variable name it's assigned to, in this case, murki
.
Inside the class, however, we refer to the object as self
.
So, while outside the class we might set an attribute like this: murki.name = "Murki"
,
inside the class we do the same using self
: self.name = "Murki"
.
That's exactly what we did when we updated the __init__
method in the Dog
class,
we set three attributes, name
, age
, and energy
,
and assigned them the values "Murki", 3, and 50, respectively.
Now, everytime we create a dog, they will automatically have name
, age
and
energy
attributes:
>>> murki = Dog() >>> murki.name, murki.age, murki.energy ('Murki', 3, 50) >>> llesi = Dog() >>> llesi.name, llesi.age, llesi.energy ('Murki', 3, 50) >>>
But as we see, these attributes will have the same values too, which doesn't make much sense, creating multiple dogs with the same name, age and energy level.
Just like any other method, __init__
can have extra parameters, beside self
,
and their arguments are passed on instance creation.
class Dog: def __init__(self, a, b, c): self.name = a self.age = b self.energy = c
>>> murki = Dog("Murki", 3, 50) >>> murki.name, murki.age, murki.energy ('Murki', 3, 50)
-
"Murki"
is assigned to parametera
, and then its value is assigned to attributename
-
3
is assigned to parameterb
, and then its value is assigned to attributeage
-
50
is assigned to parameterc
, and then its value is assigned to attributeenergy
Now we can create multiple dogs with same attributes, different values
>>> murki = Dog("Murki", 3, 50) >>> murki.name, murki.age, murki.energy ('Murki', 3, 50) >>> llesi = Dog("Llesi", 1, 70) >>> llesi.name, llesi.age, llesi.energy ('Llesi', 1, 70) >>>
Most of the time it is a good idea to name parameters the same as attributes; logically they represent the same thing:
class Dog: def __init__(self, name, age, energy): self.name = name self.age = age self.energy = energy
Previously we used set_info
to set dog attributes and their values, now we use __init__
.
We see that these two methods have the same parameters and the same body implementation.
The only difference is their names. So from now on we won't need set_info
method
since its functionality is replaced by__init__
. Here is the final version of our class:
class Dog: """Represents a dog. attributes: name: str, age: int, energy: float """ def __init__(self, name, age, energy): self.name = name self.age = age self.energy = energy def print(self): print(f'Name: {self.name}, Age: {self.age}')
>>> murki = Dog("Murki", 2, 50) >>> murki.print() Name: Murki, Age: 2