17.6. OOP Init

  • __init__() is an initializer method

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

  • All classes has default __init__() which does nothing by default

  • You can create your own initializer method and override the default

constructor

Method called when Python creates an instance of a class. Constructor is responsible for creating an object. Constructor returns an instance.

initializer

Method called when Python creates an instance of a class. Initializer is responsible for initializing empty object with values. Initializer should return None.

17.6.1. Initialization

  • __init__() is an initializer method

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

  • All classes has default __init__() which does nothing by default

  • You can create your own initializer method and override the default

Initializer method without arguments:

>>> class User:
...     def __init__(self):
...         print('hello')
>>>
>>>
>>> alice = User()
hello
>>>
>>> bob = User()
hello

17.6.2. Parameters and Arguments

  • Parameters - specified in method signature definition

  • Arguments - passed to the method on call

  • Required parameters - if not passed, TypeError will be raised

  • Optional parameters - if not passed, the default value will be used

  • Positional argument - passed as value to the method

  • Keyword argument - passed as name=value to the method

>>> class User:
...     def __init__(self, a, b=None):
...         print(f'Hello {a=} {b=}')
>>>
>>>
>>> alice = User()
Traceback (most recent call last):
TypeError: User.__init__() missing 1 required positional argument: 'a'
>>>
>>> alice = User('alice', 'secret')
Hello a='alice' b='secret'
>>>
>>> alice = User(a='alice', b='secret')
Hello a='alice' b='secret'

However, all that will not save in the object, and all variables will be destroyed upon __init__() completion.

>>> vars(alice)
{}

17.6.3. Attributes Initialization

  • Init can initialize instance attributes with a value

>>> class User:
...     def __init__(self):
...         self.authenticated = False
>>>
>>>
>>> alice = User()
>>>
>>> vars(alice)
{'authenticated': False}

17.6.4. Attributes Parametrization

  • You can set initial value for instance attributes based on arguments passed to the __init__() on object creation

>>> class User:
...     def __init__(self, a, b):
...         self.username = a
...         self.password = b
>>>
>>>
>>> alice = User('alice', 'secret')
>>> alice = User(a='alice', b='secret')

Only when you assign a value to self.something, then it will be stored as a instance attribute:

>>> vars(alice)
{'username': 'alice', 'password': 'secret'}

17.6.5. Convention

  • Use the same parameter names as instance attribute names

>>> class User:
...     def __init__(self, username, password):
...         self.username = username
...         self.password = password
>>>
>>>
>>> alice = User('alice', 'secret')
>>> alice = User(username='alice', password='secret')
>>>
>>> vars(alice)
{'username': 'alice', 'password': 'secret'}

17.6.6. Attribute Validation

  • For example minimum password length validation

>>> class User:
...     def __init__(self, username, password):
...         if len(password) < 8:
...             raise ValueError('Password must be at least 8 characters')
...         self.username = username
...         self.password = password
>>>
>>>
>>> alice = User('alice', 'secret')
Traceback (most recent call last):
ValueError: Password must be at least 8 characters
>>>
>>> alice = User('alice', 'secret123')
>>>
>>> vars(alice)
{'username': 'alice', 'password': 'secret123'}

17.6.7. Use Case - 1

>>> class Point:
...     def __init__(self, x, y):
...         self.x = x
...         self.y = y
>>>
>>>
>>> a = Point(10, 20)
>>> b = Point(10, y=20)
>>> c = Point(x=10, y=20)
>>> d = Point(y=20, x=10)

17.6.8. Use Case - 2

>>> class Point:
...     def __init__(self, x, y, z=0):
...         self.x = x
...         self.y = y
...         self.z = z
>>> a = Point(10, 20)
>>> b = Point(10, y=20)
>>> c = Point(x=10, y=20)
>>> d = Point(y=20, x=10)
>>> e = Point(10, 20, 30)
>>> f = Point(10, 20, z=30)
>>> g = Point(10, y=20, z=30)
>>> h = Point(10, z=30, y=20)
>>> i = Point(x=10, y=20, z=30)
>>> j = Point(x=10, z=30, y=20)
>>> k = Point(y=20, x=10, z=30)
>>> l = Point(y=20, z=30, x=10)
>>> m = Point(z=30, x=10, y=20)
>>> n = Point(z=30, y=20, x=10)

17.6.9. Use Case - 3

>>> 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')
>>> virginica = Iris(
...     sepal_length=5.8,
...     sepal_width=2.7,
...     petal_length=5.1,
...     petal_width=1.9,
...     species='virginica')

17.6.10. Use Case - 4

>>> from random import randint, seed
>>> seed(0)
>>>
>>>
>>> class Hero:
...     def __init__(self, name, position_x, position_y):
...         self.name = name
...         self.position = (position_x, position_y)
...         self.health = randint(50,100)
>>>
>>>
>>> alice = Hero('Alice', position_x=10, position_y=20)
>>> vars(alice)
{'name': 'Alice', 'position': (10, 20), 'health': 74}

17.6.11. Use Case - 5

>>> from random import randint, seed
>>> seed(0)
>>>
>>>
>>> class Hero:
...     def __init__(self, name, health_min=10, health_max=100):
...         self.name = name
...         self.position = (0, 0)
...         self.health = randint(health_min,health_max)
>>>
>>>
>>> alice = Hero('Alice', health_min=50)
>>> vars(alice)
{'name': 'Alice', 'position': (0, 0), 'health': 74}

17.6.12. Assignments

# %% About
# - Name: OOP Init Hello
# - Difficulty: easy
# - Lines: 2
# - Minutes: 2

# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author

# %% English
# 1. Modify `User` class:
#    - Define initialization method
#    - Method should print 'hello' at object creation
# 2. Non-functional requirements:
#    - Do not store any values in the class
#    - Run doctests - all must succeed

# %% Polish
# 1. Zmodyfikuj klasę `User`:
#    - Zdefiniuj metodę inicjalizacyjną
#    - Metoda powinna wypisać 'hello' przy tworzeniu obiektu
# 2. Wymagania niefunkcjonalne:
#    - Nie przechowuj żadnych wartości w klasie
#    - Uruchom doctesty - wszystkie muszą się powieść

# %% Doctests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'

>>> from inspect import isclass

>>> assert isclass(User)
>>> assert hasattr(User, '__init__')

>>> result = User()
hello
>>> vars(result)
{}
"""

# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -f -v myfile.py`

# %% Imports

# %% Types
from typing import Callable
User: type
__init__: Callable[[object], None]

# %% Data

# %% Result
class User:
    ...

# %% About
# - Name: OOP Init Fields
# - Difficulty: easy
# - Lines: 3
# - Minutes: 2

# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author

# %% English
# 1. Modify `User` class:
#    - Define initialization method
#    - Method should set `authenticated` attribute to `False`
# 2. Non-functional requirements:
#    - Run doctests - all must succeed

# %% Polish
# 1. Zmodyfikuj klasę `User`:
#    - Zdefiniuj metodę inicjalizacyjną
#    - Metoda powinna ustawić atrybut `authenticated` na `False`
# 2. Wymagania niefunkcjonalne:
#    - Uruchom doctesty - wszystkie muszą się powieść

# %% Doctests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'

>>> from inspect import isclass

>>> assert isclass(User)
>>> assert hasattr(User, '__init__')

>>> result = User()
>>> vars(result)
{'authenticated': False}
"""

# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -f -v myfile.py`

# %% Imports

# %% Types
from typing import Callable
User: type
__init__: Callable[[object], None]
authenticated: bool

# %% Data

# %% Result
class User:
    ...

# %% About
# - Name: OOP Init Parameters
# - Difficulty: easy
# - Lines: 3
# - Minutes: 2

# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author

# %% English
# 1. Modify `User` class:
#    - Define initialization method with parameters `firstname` and `lastname`
#    - Method should set `firstname` attribute to the value of `firstname` parameter
#    - Method should set `lastname` attribute to the value of `lastname` parameter
# 2. Non-functional requirements:
#    - Run doctests - all must succeed

# %% Polish
# 1. Zmodyfikuj klasę `User`:
#    - Zdefiniuj metodę inicjalizacyjną z parametrami `firstname` i `lastname`
#    - Metoda powinna ustawić atrybut `firstname` na wartość parametru `firstname`
#    - Metoda powinna ustawić atrybut `lastname` na wartość parametru `lastname`
# 2. Wymagania niefunkcjonalne:
#    - Uruchom doctesty - wszystkie muszą się powieść

# %% Doctests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'

>>> from inspect import isclass

>>> assert isclass(User)
>>> assert hasattr(User, '__init__')

>>> alice = User('Alice', 'Apricot')
>>> vars(alice)
{'firstname': 'Alice', 'lastname': 'Apricot'}

>>> bob = User(firstname='Bob', lastname='Blackthorn')
>>> vars(bob)
{'firstname': 'Bob', 'lastname': 'Blackthorn'}
"""

# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -f -v myfile.py`

# %% Imports

# %% Types
from typing import Callable
User: type
__init__: Callable[[object], None]
firstname: str
lastname: str

# %% Data

# %% Result
class User:
    ...