9.5. Methods and Attributes

9.5.1. Rationale

  • Methods are functions in the class

  • First argument is always instance (self)

  • While calling function you never pass self

  • Prevents copy-paste code

  • Improves readability

  • Improves refactoring

  • Decomposes bigger problem into smaller chunks

Listing 9.26. Syntax
class MyClass:
    def __init__(self)
        self.myfield = 'some value'

    def mymethod(self):
        print(self.myfield)


my = MyClass()
my.mymethod()
# 'some value'

9.5.2. Methods Accessing Fields

Listing 9.27. Methods Accessing Fields
class Astronaut:
    def __init__(self, name):
        self.name = name

    def say_hello(self):
        print(f'My name... {self.name}')


jose = Astronaut('José Jiménez')
jose.say_hello()
# My name... José Jiménez
Listing 9.28. self.name must be defined before accessing.
class Astronaut:
    def say_hello(self):
        print(f'My name... {self.name}')


jose = Astronaut()
jose.say_hello()
# Traceback (most recent call last):
#     ...
# AttributeError: 'Astronaut' object has no attribute 'name'

9.5.3. Methods Calling Other Methods

Listing 9.29. Methods Calling Other Methods
class Astronaut:
    def get_name(self):
        return 'José Jiménez'

    def say_hello(self):
        name = self.get_name()
        print(f'My name... {name}')


jose = Astronaut()
jose.say_hello()
# My name... José Jiménez
Listing 9.30. Methods calling other methods
class Iris:
    def __init__(self):
        self.sepal_length = 5.1
        self.sepal_width = 3.5
        self.petal_length = 1.4
        self.petal_width = 0.2

    def sepal_area(self):
        return self.sepal_length * self.sepal_width

    def petal_area(self):
        return self.petal_length * self.petal_width

    def total_area(self):
        return self.sepal_area() + self.petal_area()


flower = Iris()
print(flower.total_area())
# Total area: 18.13
Listing 9.31. 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 = 5.8
    sepal_width: float = 2.7
    petal_length: float = 5.1
    petal_width: float = 1.9
    species: str = 'Iris'

    def sepal_area(self):
        return self.sepal_length * self.sepal_width

    def petal_area(self):
        return self.petal_length * self.petal_width

    def total_area(self):
        return self.sepal_area() + self.petal_area()


flower = Iris()
print(flower.total_area())
# Total area: 18.13

9.5.4. Examples

$ pip install atlassian-python-api
from atlassian import Jira

jira = Jira(
    url='http://localhost:8080',
    username='admin',
    password='admin')

JQL = 'project = DEMO AND status IN ("To Do", "In Progress") ORDER BY issuekey'

result = jira.jql(JQL)
print(result)
from atlassian import Confluence

confluence = Confluence(
    url='http://localhost:8090',
    username='admin',
    password='admin')

result = confluence.create_page(
    space='DEMO',
    title='This is the title',
    body='This is the body. You can use <strong>HTML tags</strong>!')

print(result)
class Point:
    def __init__(self, x, y, z):
        self.x = x
        self.y = y
        self.z = z

    def get_coordinates(self):
        return self.x, self.y, self.z

    def show(self):
        print(f'Point(x={self.x}, y={self.y}, z={self.z})')


point = Point(x=1, y=2, z=3)

print(point.x)      # 1
print(point.y)      # 2
print(point.z)      # 3

point.get_coordinates()
# (1, 2, 3)

point.show()
# Point(x=1, y=2, z=3)

9.5.5. Assignments

9.5.5.1. OOP Method Sequence

  • Assignment name: OOP Method Sequence

  • Last update: 2020-10-01

  • Complexity level: easy

  • Lines of code to write: 18 lines

  • Estimated time of completion: 13 min

  • Solution: solution/oop_method_sequence.py

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

  2. Create class Iris with features: list[float] and label: str attributes

  3. For each row in DATA create Iris instance with row values

  4. Set class attributes at the initialization from positional arguments

  5. Create method which sums values of all features

  6. Print species name and a sum method result

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

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

  2. Stwórz klasę Iris z atrybutami features: list[float] i label: str

  3. Dla każdego wiersza w DATA twórz instancję Iris z danymi z wiersza

  4. Ustaw atrybuty klasy przy inicjalizacji z argumentów pozycyjnych

  5. Stwórz metodę sumującą wartości wszystkich features

  6. Wypisz nazwę gatunku i wynik metody sumującej

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

Input
DATA = [
    (4.7, 3.2, 1.3, 0.2, 'setosa'),
    (7.0, 3.2, 4.7, 1.4, 'versicolor'),
    (7.6, 3.0, 6.6, 2.1, 'virginica'),
]
Output
setosa 9.4
versicolor 16.299999999999997
virginica 19.3

9.5.5.2. OOP Method Nested

  • Assignment name: OOP Method Nested

  • Last update: 2020-10-01

  • Complexity level: medium

  • Lines of code to write: 15 lines

  • Estimated time of completion: 21 min

  • Solution: solution/oop_method_nested.py

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

  2. Define class Iris

  3. Iris has:

    • "Sepal length" type float

    • "Sepal width" type float

    • "Petal length" type float

    • "Petal width" type float

    • "Species" type str

  4. Iris can:

    • Return number of float type attributes

    • Return list of all float type attributes

    • Return sum of values of all float type attributes

    • Return mean of all float type attributes

  5. Use self.__dict__ iteration to return values of numeric fields

  6. Create setosa object with attributes set at the initialization

  7. Create virginica object with attributes set at the initialization

  8. Print sum, mean and species name of each objects

  9. Do not use @dataclass

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

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

  2. Zdefiniuj klasę Iris

  3. Iris ma:

    • "Sepal length" typu float

    • "Sepal width" typu float

    • "Petal length" typu float

    • "Petal width" typu float

    • "Species" typu str

  4. Iris może:

    • Zwrócić liczbę pól typu float

    • Zwrócić listę wartości wszystkich pól typu float

    • Zwrócić sumę wartości pól typu float

    • Zwrócić średnią arytmetyczną wartość pól typu float

  5. Użyj iterowania po self.__dict__ do zwrócenia wartości pól numerycznych

  6. Stwórz obiekt setosa z atrybutami ustawionymi przy inicjalizacji

  7. Stwórz obiekt virginica z atrybutami ustawionymi przy inicjalizacji

  8. Wypisz sumę, średnią oraz nazwę gatunku każdego z obiektów

  9. Nie używaj @dataclass

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

Input
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(5.8, 2.7, 5.1, 1.9, 'virginica')

print(setosa.show())
print(virginica.show())
Output
total=10.20 mean=2.55 setosa
total=15.50 mean=3.88 virginica
Hints
  • isinstance(value, float)