9.4. Methods

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

method

Function inside the class which takes self as a first argument.

point_x = 1
point_y = 2
point_z = 3

print(point_x, point_y, point_z)
# 1 2 3
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 to_string(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.to_string()
# Point(x=1, y=2, z=3)

9.4.2. Methods Without Arguments

Listing 9.25. Methods without arguments
class Astronaut:
    def say_hello(self):
        print('My name... José Jiménez')


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

9.4.3. Methods With Required Argument

Listing 9.26. Methods with required argument
class Astronaut:
    def say_hello(self, name):
        print(f'My name... {name}')


jose = Astronaut()

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

jose.say_hello('José Jiménez')
# My name... José Jiménez

jose.say_hello()
# TypeError: say_hello() missing 1 required positional argument: 'name'

9.4.4. Methods With Optional Argument

Listing 9.27. Methods with arguments with default value
class Astronaut:
    def say_hello(self, name='Unknown'):
        print(f'My name... {name}')


jose = Astronaut()

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

jose.say_hello('José Jiménez')
# My name... José Jiménez

jose.say_hello()
# My name... Unknown

9.4.5. Methods Accessing Fields

Listing 9.28. 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.29. self.name must be defined before accessing.
class Astronaut:
    def say_hello(self):
        print(f'My name... {self.name}')


jose = Astronaut()
jose.say_hello()
# AttributeError: 'Astronaut' object has no attribute 'name'

9.4.6. Methods Calling Other Methods

Listing 9.30. 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.31. 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.32. 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.4.7. 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)

9.4.8. Assignments

9.4.8.1. OOP Method Sequence

English
  1. Create class Iris with features: List[float] and label: str attributes

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

  3. Set class attributes at the initialization from positional arguments

  4. Create method which sums values of all features

  5. Print species name and a sum method result

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

Polish
  1. Stwórz klasę Iris z atrybutami features: List[float] i label: str

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

  3. Ustaw atrybuty klasy przy iniclalizacji z argumentów pozycyjnych

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

  5. Wyisz nazwę gatunku i wynik metody sumującej

  6. 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.4.8.2. OOP Methods

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 values from self.__dict__ to check for type or length

  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 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 wartości self.__dict__ do sprawdzania typu lub długości

  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ę każdego z obiektów

  9. Nie używaj @dataclass

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

Input
setosa = Iris(5.1, 3.5, 1.4, 0.2, 'setosa')
virginica = Iris(5.8, 2.7, 5.1, 1.9, 'virginica')
Output
total=10.20 mean=2.55 setosa
total=15.50 mean=3.88 virginica