9.4. Init Method

9.4.1. Rationale

  • It's a first method run after object is initiated

  • All classes has default __init__()

constructor

Method called at object instantiation used to create object. Constructor is called on not fully initialized object and hence do not have access to object methods. Constructor should return None.

initializer

Method called at object instantiation used to fill empty object with values. Initializer is called upon object initialization and hence can modify object and use its methods. Initializer should return None.

9.4.2. Syntax

class Astronaut:
    def __init__(self, firstname, lastname):
        astro.firstname = firstname
        astro.lastname = lastname


astro = Astronaut('Mark', 'Watney')

print(astro.firstname)
print(astro.lastname)

9.4.3. Initializer Method Without Arguments

Listing 9.17. Initializer method without arguments
class Astronaut:
    def __init__(self):
        print('My name... José Jiménez')


jose = Astronaut()
# My name... José Jiménez

9.4.4. Initializer Method With Arguments

Listing 9.18. Initializer method with arguments
class Astronaut:
    def __init__(self, firstname, lastname='Unknown'):
        print(f'My name... {firstname} {lastname}')


jan = Astronaut('Jan')
# My name... Jan

jose = Astronaut('José', 'Jiménez')
# My name... José Jiménez

melissa = Astronaut('Melissa', lastname='Lewis')
# My name... Melissa Lewis

mark = Astronaut(firstname='José', lastname='Jiménez')
# My name... José Jiménez

ryan = Astronaut(lastname='Stone', firstname='Ryan')
# My name... Ryan Stone

ivan = Astronaut()
# Traceback (most recent call last):
#     ...
# TypeError: __init__() missing 1 required positional argument: 'firstname'

9.4.5. Constant Attributes

Listing 9.19. Init time attributes
class Astronaut:
    def __init__(self):
        self.firstname = 'Mark'
        self.lastname = 'Watney'


mark = Astronaut()
print(mark.firstname)       # Mark
print(mark.lastname)        # Watney
print(mark.missions)        # AttributeError: 'Astronaut' object has no attribute 'mission'

ivan = Astronaut()
print(ivan.firstname)       # Mark
print(ivan.lastname)        # Watney
print(ivan.missions)        # AttributeError: 'Astronaut' object has no attribute 'mission'

9.4.6. Variable Attributes

Listing 9.20. Init time attributes
class Astronaut:
    def __init__(self, a, b):
        self.firstname = a
        self.lastname = b


mark = Astronaut('Mark', 'Watney')
print(mark.firstname)       # Mark
print(mark.lastname)        # Watney
print(mark.missions)        # AttributeError: 'Astronaut' object has no attribute 'mission'

ivan = Astronaut(a='Ivan', b='Ivanovich')
print(ivan.firstname)       # Ivan
print(ivan.lastname)        # Ivanovich
print(ivan.missions)        # AttributeError: 'Astronaut' object has no attribute 'mission'
Listing 9.21. Init time attributes
class Astronaut:
    def __init__(self, firstname, lastname):
        self.firstname = firstname
        self.lastname = lastname


mark = Astronaut('Mark', 'Watney')
print(mark.firstname)       # Mark
print(mark.lastname)        # Watney
print(mark.missions)        # AttributeError: 'Astronaut' object has no attribute 'mission'

ivan = Astronaut(firstname='Ivan', lastname='Ivanovich')
print(ivan.firstname)       # Ivan
print(ivan.lastname)        # Ivanovich
print(ivan.missions)        # AttributeError: 'Astronaut' object has no attribute 'mission'
Listing 9.22. Init time attributes
class Astronaut:
    def __init__(self, firstname, lastname):
        self.name = f'{firstname} {lastname}'


mark = Astronaut('Mark', 'Watney')

print(mark.name)           # Mark Watney
print(mark.firstname)      # AttributeError: 'Astronaut' object has no attribute 'firstname'
print(mark.lastname)       # AttributeError: 'Astronaut' object has no attribute 'lastname'
Listing 9.23. Init time attributes
class Point:
    def __init__(self, x, y, z=0):
        self.x = x
        self.y = y
        self.z = z


p1 = Point(10, 20)
p2 = Point(x=10, y=20)
p3 = Point(10, 20, 30)
p4 = Point(10, 20, z=30)
p5 = Point(x=10, y=20, z=30)
Listing 9.24. Init time attributes
class Iris:
    def __init__(self, sepal_length, sepal_width,
                 petal_length, petal_width, species):

        self.sepal_length = sepal_length
        self.sepal_width = sepal_width
        self.petal_length = petal_length
        self.petal_width = petal_width
        self.species = species


setosa = Iris(5.1, 3.5, 1.4, 0.2, 'setosa')

print(setosa.sepal_length)      # 5.1
print(setosa.sepal_width)       # 3.5
print(setosa.petal_length)      # 1.4
print(setosa.petal_width)       # 0.2
print(setosa.species)           # setosa


virginica = Iris(
    sepal_length=5.8,
    sepal_width=2.7,
    petal_length=5.1,
    petal_width=1.9,
    species='virginica')

print(virginica.__dict__)
# {'sepal_length': 5.8,
#  'sepal_width': 2.7,
#  'petal_length': 5.1,
#  'petal_width': 1.9,
#  'species': 'virginica'}
Listing 9.25. Since Python 3.7 there is a @dataclass decorator, which automatically generates __init__() arguments and fields. More information in OOP Dataclass.
from dataclasses import dataclass


@dataclass
class Iris:
    sepal_length: float
    sepal_width: float
    petal_length: float
    petal_width: float
    species: str = 'Iris'


setosa = Iris(5.1, 3.5, 1.4, 0.2, 'setosa')

print(setosa.sepal_length)      # 5.1
print(setosa.sepal_width)       # 3.5
print(setosa.petal_length)      # 1.4
print(setosa.petal_width)       # 0.2
print(setosa.species)           # setosa


virginica = Iris(
    sepal_length=5.8,
    sepal_width=2.7,
    petal_length=5.1,
    petal_width=1.9,
    species='virginica')

print(virginica.__dict__)
# {'sepal_length': 5.8,
#  'sepal_width': 2.7,
#  'petal_length': 5.1,
#  'petal_width': 1.9,
#  'species': 'virginica'}

9.4.7. Checking Values

class Kelvin:
    MINIMAL_VALUE = 0.0

    def __init__(self, value):
        if type(value) not in (float, int):
            raise TypeError('Temperature must be int or float')
        if value < self.MINIMAL_VALUE:
            raise ValueError('Temperature must be greater than 0')
        self.value = value


a = Kelvin(273.15)
print(a.value)
# 273.15

b = Kelvin(-300)
# Traceback (most recent call last):
#     ...
# ValueError: Temperature must be greater than 0

9.4.8. Assignments

9.4.8.1. OOP Init Print

  • Assignment name: OOP Init Print

  • Last update: 2020-10-01

  • Complexity level: easy

  • Lines of code to write: 10 lines

  • Estimated time of completion: 3 min

  • Solution: solution/oop_init_print.py

English
  1. Create one class Temperature

  2. Create three instances of Temperature class

  3. Values must be passed at the initialization

  4. At initialization instances print:

    • Instance celsius prints temperature 36.6

    • Instance fahrenheit prints temperature 97.88

    • Instance kelvin prints temperature 309.75

  5. Do not convert units (print only given numbers)

  6. Do not store values in the instances (only print on instance creation)

  7. Do not use @dataclass

  8. Compare result with "Output" section (see below)

Polish
  1. Stwórz jedną klasę Temperature

  2. Stwórz trzy instancje klasy Temperature

  3. Wartości mają być podawane przy inicjalizacji

  4. Przy inicjalizacji instancje wypisują:

    • Instancja celsius wyświetla temperaturę 36.6

    • Instancja fahrenheit wyświetla temperaturę 97.88

    • Instancja kelvin wyświetla temperaturę 309.75

  5. Nie konwertuj jednostek (użyj tylko podanych numerów)

  6. Nie przechowuj informacji w instancjach (tylko wypisz przy inicjalizacji)

  7. Nie używaj @dataclass

  8. Porównaj wyniki z sekcją "Output" (patrz poniżej)

Output
36.6
97.88
309.75

9.4.8.2. OOP Init Model

  • Assignment name: OOP Init Model

  • Last update: 2020-10-01

  • Complexity level: easy

  • Lines of code to write: 15 lines

  • Estimated time of completion: 8 min

  • Solution: solution/oop_init_model.py

English
  1. Use data from "Input" section (see below)

  2. Model the data using classes

  3. Create instances for each record

  4. Values must be passed at the initialization

  5. Create instances of a first class using positional arguments

  6. Create instances of a second class using keyword arguments

  7. Using __dict__ print all fields from each instance

  8. Do not use @dataclass

Polish
  1. Użyj danych z sekcji "Input" (patrz poniżej)

  2. Zamodeluj dane za pomocą klas

  3. Stwórz instancje dla każdego wpisu

  4. Wartości mają być podawane przy inicjalizacji

  5. Twórz instancje pierwszej klasy używając argumentów pozycyjnych

  6. Twórz instancje drugiej klasy używając argumentów nazwanych

  7. Za pomocą __dict__ wypisz wszystkie pola każdej z instancji

  8. Nie używaj @dataclass

Input
Mark Watney, USA, 1969-07-21
National Aeronautics and Space Administration, USA, 1958-07-29

Jan Twardowski, Poland, 1961-04-12
Polish Space Agency, Poland, 2014-09-26
The whys and wherefores