4. Passing many arguments

4.1. Operators * i **

  • To nie jest mnożenie i potęgowanie!
  • * zwykle nazywa się *args (arguments) - argumenty pozycyjne (anonimowe)
  • ** zwykle nazywa się **kwargs (keyword arguments) - argumenty nazwane
  • *args unpack tuple or list
  • **kwargs unpack dict

4.2. * unpacks list or tuple

complex(3, 5)
args = (3, 5)
complex(*args)

4.3. ** unpacks dict

complex(real=3, imag=5)
kwargs = {'real': 3, 'imag': 5}
complex(**number)

4.4. Przekazywanie do funkcji zmiennej ilości parametrów

Przykładowe zastosownaie operatorów * i ** polega na wykorzystaniu ich przy wywołaniu funkcji. Wtedy, wykorzystując operator *, kolejne elementy listy albo krotki będą przekazane jako kolejne argumenty funkcji, a wykorzystując operator ** kolejne elementy zmiennej słownikowej będą przekazane jako nazwane argumenty. Oznacza to, że na przykład argument x funkcji, przyjmie wartość vector['x'].

def my_function(x, y, z):
    print(x, y, z)

vector = (1, 0, 1)
my_function(*vector)   # my_function(1, 0, 1)
# 1, 0, 1

vector = {'y': 1, 'x': 0, 'z': 1}
my_function(**vector)  # my_function(y=1, x=0, z=1)
# 0, 1, 1
def wyswietl(a, b, c=0):
    print(locals())

wyswietl(1, 2, 3)
# {'a': 1, 'b': 2, 'c': 3}

dane = (1, 2, 3)
wyswietl(*dane)
# {'a': 1, 'b': 2, 'c': 3}

dane = (1, 2)
wyswietl(*dane)
# {'a': 1, 'b': 2, 'c': 0}
def wyswietl(a, b, c=0, *args):
    print(locals())

dane = (1, 2, 3, 4)
wyswietl(*dane)
# {'a': 1, 'b': 2, 'c': 3, 'args': (4,)}

dane = (1, 2, 3, 4, 5, 6, 7)
wyswietl(*dane)
# {'a': 1, 'b': 2, 'c': 3, 'args': (4, 5, 6, 7)}

wyswietl(1, 2)
# {'a': 1, 'b': 2, 'c': 0, 'args': ()}
def wyswietl(a, b, c=0, *args, **kwargs):
    print(locals())

wyswietl(1, 2, x=77, y=99)
# {'a': 1, 'b': 2, 'c': 0, 'args': (), 'kwargs': {'x': 77, 'y': 99}}

wyswietl(1, 2, x=77, y=99, c=7)
# {'a': 1, 'b': 2, 'c': 7, 'args': (), 'kwargs': {'x': 77, 'y': 99}}

dane = {'x': 77, 'y': 99}
wyswietl(1, 2, 3, **dane)
# {'a': 1, 'b': 2, 'c': 3, 'args': (), 'kwargs': {'x': 77, 'y': 99}}

dane = {'a': 1, 'b': 2, 'x': 77, 'y': 99}
wyswietl(**dane)
# {'a': 1, 'b': 2, 'c': 0, 'args': (), 'kwargs': {'x': 77, 'y': 99}}
def wyswietl(a, b, c=0, *args, **kwargs):
    print(locals())

dane = {'x': 77, 'y': 99, 'a': 7}
wyswietl(1, 2, 3, **dane)
# TypeError: wyswietl() got multiple values for argument 'a'
def wyswietl(a, b, c=0, *args, **kwargs):
    print(locals())

wyswietl(1, 2, 3, 4, 5, 6, x=77, y=99)
# {'a': 1, 'b': 2, 'c': 3, 'args': (4, 5, 6), 'kwargs': {'x': 77, 'y': 99}}

pozycyjne = (4, 5, 6)
nazwane = {'x': 77, 'y': 99}
wyswietl(1, 2, 3, *pozycyjne, **nazwane)
# {'a': 1, 'b': 2, 'c': 3, 'args': (4, 5, 6), 'kwargs': {'x': 77, 'y': 99}}

4.5. Przykładowe zastosowanie

4.5.1. Konwersja Temperatury

from typing import List

def celsius_to_fahrenheit(*degrees) -> List[float]:
    return [x * 1.8 + 32 for x in degrees]


celsius_to_fahrenheit(1)
# [33.8]

celsius_to_fahrenheit(1, 2, 3, 4, 5)
# [33.8, 35.6, 37.4, 39.2, 41.0]

4.5.2. Podawanie parametrów do funkcji

def rysuj_wykres(a, b, color, linia):
    print(locals())


rysuj_wykres(1, 2, color='czerwony', linia='przerywana')
rysuj_wykres(3, 4, color='czerwony', linia='przerywana')
rysuj_wykres(5, 6, color='czerwony', linia='przerywana')
def rysuj_wykres(a, b, color, linia):
    print(locals())


parametry = {
    'color': 'czerwony',
    'linia': 'przerywana',
}

rysuj_wykres(1, 2, **parametry)
rysuj_wykres(3, 4, **parametry)
rysuj_wykres(5, 6, **parametry)

4.5.3. Placeholder class

class Kontakt:
    def __init__(self, **kwargs):
        for key, value in kwargs.items():
            setattr(self, key, value)

Kontakt(imie='Pan', nazwisko='Twardowski')

4.5.5. Calling function with all variables from higher order function

def wyswietl(*args, **kwargs):
    print(f'args: {args}')
    print(f'kwargs: {kwargs}')

def function(a, b, c=0):
    x = 4
    y = 5

    wyswietl(**locals())

function(1, 2)
# args: ()
# kwargs: {'a': 1, 'b': 2, 'c': 0, 'x': 4, 'y': 5}

4.6. Assignments

4.6.1. Iris

  1. Otwórz link w przeglądarce i skopiuj zawartość do pliku iris.csv na dysku

  2. Sparsuj zawartość odrzucając nagłówek

  3. Dla każdego rekordu, usuń białe spacje i podziel go po przecinku ,

  4. Wyniki podziału odbierz do dwóch zmiennych:

    • features: Tuple[float] - pomiary
    • labels: Dict[str, str] - key: ‘species’, value: nazwa gatunku
  5. Stwórz funkcję print_iris(sepal_length, sepal_width, *args, **kwargs), która wyświetli zawartość wszystkich argumentów

  6. Odpalaj funkcję print_iris(), podając wartości features i labels

  7. Pomiary mają być podane pozycyjnie (*), a gatunek nazwanie (**)