12.8. OOP Init Setattr

  • 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.

12.8.1. Syntax

>>> class MyClass:
...     myattribute: str
...
...     def __init__(self, myvar):
...         self.myattribute = myvar
>>>
>>>
>>> myobj = MyClass('myvalue')
>>>
>>> print(myobj.myattribute)
myvalue

12.8.2. Constant Attributes

>>> class Astronaut:
...     def __init__(self):
...         self.firstname = 'Mark'
...         self.lastname = 'Watney'
>>>
>>>
>>> mark = Astronaut()
>>> melissa = Astronaut()
>>>
>>> vars(mark)
{'firstname': 'Mark', 'lastname': 'Watney'}
>>>
>>> vars(melissa)
{'firstname': 'Mark', 'lastname': 'Watney'}

12.8.3. Variable Attributes

>>> class Astronaut:
...     def __init__(self, a, b):
...         self.firstname = a
...         self.lastname = b
>>>
>>>
>>> mark = Astronaut('Mark', 'Watney')
>>> vars(mark)
{'firstname': 'Mark', 'lastname': 'Watney'}
>>>
>>> melissa = Astronaut(a='Melissa', b='Lewis')
>>> vars(melissa)
{'firstname': 'Melissa', 'lastname': 'Lewis'}

12.8.4. Better Names

>>> class Astronaut:
...     def __init__(self, firstname, lastname):
...         self.firstname = firstname
...         self.lastname = lastname
>>>
>>>
>>> mark = Astronaut('Mark', 'Watney')
>>> vars(mark)
{'firstname': 'Mark', 'lastname': 'Watney'}
>>>
>>> melissa = Astronaut(firstname='Melissa', lastname='Lewis')
>>> vars(melissa)
{'firstname': 'Melissa', 'lastname': 'Lewis'}

12.8.5. Combine 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)
Traceback (most recent call last):
AttributeError: 'Astronaut' object has no attribute 'firstname'
>>>
>>> print(mark.lastname)
Traceback (most recent call last):
AttributeError: 'Astronaut' object has no attribute 'lastname'

12.8.6. Example

>>> 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)

12.8.7. Use Case - 0x01

>>> 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')

12.8.8. Use Case - 0x02

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

12.8.9. Use Case - 0x03

  • Dataclasses

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

12.8.10. Assignments

Code 12.9. Solution
"""
* Assignment: OOP Init SetAttrPositional
* Required: yes
* Complexity: easy
* Lines of code: 2 lines
* Time: 3 min

English:
    1. Modify code below
    2. Create instances of an `Astronaut` and `SpaceAgency` classes
    3. Use positional arguments to pass values at the initialization
    4. Run doctests - all must succeed

Polish:
    1. Zmodyfikuj kod poniżej
    2. Stwórz instancje klas `Astronaut` i `SpaceAgency`
    3. Użyj argumentów pozycyjnych do przekazania wartości przy inicjalizacji
    4. Uruchom doctesty - wszystkie muszą się powieść

Tests:
    >>> import sys; sys.tracebacklimit = 0

    >>> assert isinstance(mark, Astronaut)
    >>> assert isinstance(nasa, SpaceAgency)
    >>> assert 'Mark' in vars(mark).values()
    >>> assert 'USA' in vars(mark).values()
    >>> assert '1969-07-21' in vars(mark).values()
    >>> assert 'Nasa' in vars(nasa).values()
    >>> assert 'USA' in vars(nasa).values()
    >>> assert '1969-07-21' in vars(nasa).values()
"""


class Astronaut:
    def __init__(self, name, country, date):
        self.name = name
        self.country = country
        self.date = date


class SpaceAgency:
    def __init__(self, name, country, date):
        self.name = name
        self.country = country
        self.date = date


# Mark, USA, 1969-07-21
# type: Astronaut
mark = ...

# Nasa, USA, 1969-07-21
# type: SpaceAgency
nasa = ...



Code 12.10. Solution
"""
* Assignment: OOP Init SetAttrKeyword
* Required: yes
* Complexity: easy
* Lines of code: 8 lines
* Time: 5 min

English:
    1. Modify code below
    2. Create instances of an `Astronaut` and `SpaceAgency` classes
    3. Use keyword arguments to pass values at the initialization
    4. Run doctests - all must succeed

Polish:
    1. Zmodyfikuj kod poniżej
    2. Stwórz instancje klas `Astronaut` i `SpaceAgency`
    3. Użyj argumentów nazwanych do przekazania wartości przy inicjalizacji
    4. Uruchom doctesty - wszystkie muszą się powieść

Tests:
    >>> import sys; sys.tracebacklimit = 0

    >>> assert isinstance(mark, Astronaut)
    >>> assert isinstance(nasa, SpaceAgency)
    >>> assert 'Mark' in vars(mark).values()
    >>> assert 'USA' in vars(mark).values()
    >>> assert '1969-07-21' in vars(mark).values()
    >>> assert 'Nasa' in vars(nasa).values()
    >>> assert 'USA' in vars(nasa).values()
    >>> assert '1969-07-21' in vars(nasa).values()
"""


class Astronaut:
    def __init__(self, name, country, date):
        self.name = name
        self.country = country
        self.date = date


class SpaceAgency:
    def __init__(self, name, country, date):
        self.name = name
        self.country = country
        self.date = date


# Mark, USA, 1969-07-21
# type: Astronaut
mark = ...

# Nasa, USA, 1969-07-21
# type: SpaceAgency
nasa = ...