Funkcje

Funkcje to części programu wielokrotnego użytku. Pozwalają nam nadać nazwę blokowi wyrażeń, a następnie uruchamiać ten blok używając tej nazwy gdziekolwiek w programie, dowolną ilość razy. Taka operacja nazywa się wywoływanie funkcji. Już wcześniej używaliśmy wielu wbudowanych funkcji, jak len lub range.

Funkcje są prawdopodobnie najważniejszą częścią każdego poważnego programu (w każdym języku programowania), więc w tym rozdziale zbadamy różne aspekty funkcji.

Funkcje definiuje się używając słowa def. Po nim następuje nazwa identyfikująca funkcji, następnie para nawiasów, które mogą zawierać kilka nazw zmiennych, a na końcu dwukropek. Poniżej zaczyna się blok wyrażeń, które są częścią tej funkcji. Przykład pokaże, że tak naprawdę to bardzo proste:

Przykład (zapisz jako function1.py):

def say_hello():
    # Blok należący do funkcji.
    print('hello world')
# Koniec funkcji.

say_hello()  # Wywołanie funkcji.
say_hello()  # Ponowne wywołanie funkcji.

Rezultat:

$ python function1.py
hello world
hello world

Jak to działa:

Definiujemy funkcję say_hello używając składni pokazanej powyżej. Ta funkcja nie wymaga żadnych parametrów i w związku z tym nie ma żadnych zmiennych zadeklarowanych w nawiasach. Parametry funkcji są wkładane do niej podczas wywoływania, więc możemy wprowadzać do niej różne wartości i uzyskiwać odpowiednie wyniki.

Zauważ, że możemy wywołać tę samą funkcję dwukrotnie, co oznacza, ze nie musimy dwa razy pisać tego samego kodu.

Parametry funkcji

Funkcja może posiadać parametry, czyli wartości, które dostarczasz do niej. Dlatego funkcja może coś zrobić z tymi wartościami. Parametry są podobne do zmiennych, różnią sie jedynie tym, że przypisywanie wartości następuje podczas wywoływania funkcji, a użyte do tego wartości są już wcześniej przypisane do jakichś zmiennych w programie.

Parametry deklarujemy w nawiasach przy definiowaniu funkcji i oddzielamy przecinkami. Podczas wywoływania funkcji przypisujemy im wartości w ten sam sposób. Zauważ, że to, co wpisujemy podczas definiowania funkcji to parametry, zaś przypisywane im wartości to argumenty.

Przykład (zapisz jako function_param.py):

def print_max(a, b):
    if a > b:
        print(a, 'is maximum')
    elif a == b:
        print(a, 'is equal to', b)
    else:
        print(b, 'is maximum')

# wpisz zmienne bezpośrednio
print_max(3, 4)

x = 5
y = 7

# wpisz zmienne jako argumenty
print_max(x, y)

Rezultat:

$ python function_param.py
4 is maximum
7 is maximum

Jak to działa:

Definiujemy tutaj funkcję print_max w której używamy dwóch parametrów a i b. Znajdujemy największą z liczb a i b za pomocą prostej kombinacji if...else i drukujemy wartość na ekran.

Podczas pierwszego uruchomienia print_max dostarczamy bezpośrednio wartości do parametrów (czyli argumenty). Za drugim razem wywołujemy ją używając dwóch zmiennych. Linijka print_max sprawia, że wartość argumentu x zostaje przekazana parametrowi a, a wartość argumentu y parametrowi b. W obu przypadkach funkcja działa tak samo.

Zmienne lokalne

Gdy deklarujesz zmienne w definicji funkcji, nie są one połączone w żaden sposób z innymi zmiennymi o tych samych nazwach, ale użytych w innej części programu. Innymi słowy, te zmienne są lokalne dla tej funkcji. To nazywa się zakres parametru. Każda zmienna ma swój zakres, czyli blok, w którym została zadeklarowana, zaczynając od miejsca zdefiniowania jej nazwy.

Przykład (zapisz jako function_local.py):

x = 50


def func(x):
    print('x is', x)
    x = 2
    print('Changed local x to', x)


func(x)
print('x is still', x)

Rezultat:

$ python function_local.py
x is 50
Changed local x to 2
x is still 50

Jak to działa:

Za pierwszym razem, gdy w funkcji używamy wartości zmiennej x, Python używa wartości zmiennej zadeklarowanej w funkcji.

Następnie zmiennej x przypisujemy wartość 2. Nazwa x jest lokalna dla naszej funkcji, więc gdy zmieniamy wartość x w funkcji, x zdefiniowane w bloku głównym pozostaje bez zmian.

Wywołując print po raz ostatni, pokazujemy wartość x w bloku głównym i udowadniamy, że nie została naruszona przez lokalne przypisanie w środku poprzednio wywołanej funkcji.

Użycie wyrażenia global

Jeżeli wewnątrz funkcji chcesz przypisać wartość do nazwy zdefiniowanej w głównym bloku programu (czyli poza funkcjami i klasami), musisz powiedzieć Pythonowi, że nazwa nie jest lokalna, ale globalna. Można to zrobić za pomocą wyrażenia global. Nie da się przypisać wartości do zmiennej zdefiniowanej poza funkcją bez użycia tego wyrażenia.

Możesz używać wartości zmiennych znajdujących się poza funkcją (zakładając, że w jej wnętrzu nie ma innej zmiennej o tej samej nazwie). Jednakże to nie jest najlepszym rozwiązaniem i powinieneś tego unikać, ponieważ wtedy czytający program nie wie, gdzie dokładnie zmienna została zadeklarowana. Użycie wyrażenia global wyraźnie pokazuje, że zmienna jest zdefiniowana w bloku głównym.

Przykład (zapisz jako function_global.py):

x = 50


def func():
    global x

    print('x is', x)
    x = 2
    print('Changed global x to', x)


func()
print('Value of x is', x)

Rezultat:

$ python function_global.py
x is 50
Changed global x to 2
Value of x is 2

Jak to działa:

Używamy wyrażenia global w celu zadeklarowania, że x jest zmienną globalną — w związku z tym, gdy przypisujemy jakąś wartość do x we wnętrzu funkcji, widać tę zmianę również wtedy, gdy używamy x w głównym bloku programu.

Możesz określać więcej niż jedną zmienną globalną w tej samej linijce, na przykład global x, y, z.

Domyślne wartości argumentów

W przypadku niektórych funkcji możesz zażyczyć sobie, aby niektóre parametry były opcjonalne i żeby przyjmowały domyślne wartości, gdy użytkownik nie chce wprowadzać do nich własnych argumentów. Możesz nadać domyślną wartość parametrowi tak, jakbyś przypisywał wartość zmiennej, czyli stawiając po nim znak przypisania (=) a następnie wartość, jaką ma przyjąć.

Pamiętaj, że domyślna wartość powinna być stałą. Dokładniej mówiąc, wartość parametru powinna być niezmienna — powód poznasz później. Na razie ważne jest jedynie, abyś o tym pamiętał.

Przykład (zapisz jako function_default.py):

def say(message, times=1):
    print(message * times)

say('Hello')
say('World', 5)

Rezultat:

$ python function_default.py
Hello
WorldWorldWorldWorldWorld

Jak to działa:

Funkcja say ma wypisywać podaną jej wiadomość określoną ilość razy. Jeżeli nie podamy wartości, napis zostanie wyświetlony domyślnie, czyli raz. Osiągnęliśmy to przez przypisanie domyślnej wartości 1 do parametru times.

Przy pierwszym użyciu tej funkcji podaliśmy jedynie napis, który dzięki temu został wyświetlony jedynie raz. Za drugim razem, oprócz napisu dołożyliśmy argument 5, a zatem uzyskaliśmy 5 powtórzeń napisu.

Ważne!
Domyślne wartości mogą posiadać jedynie te parametry, które są na końcu listy. Innymi słowy, nie możesz nadać wartości domyślnej parametrowi, jeżeli po nim wystąpi taki, który nie będzie jej posiadał (idąc wzdłuż ciągu parametrów danej funkcji). Jest to spowodowane tym, że wartości są przypisywane według kolejności występowania parametrów. Na przykład możesz napisać def funkcja(a, b = 5), ale nie możesz napisać def funkcja(a = 5, b)!

Argumenty ze słowem kluczowym

Jeżeli używasz funkcji z wieloma parametrami i chcesz podać tylko niektóre z nich, możesz przypisywać wartości przez nazywanie ich — mówimy na to argumenty ze słowem kluczowym. Używamy nazwy (słowa kluczowego) zamiast właściwej pozycji (jak dotychczas zawsze robiliśmy), aby przekazać funkcji argumenty.

Są dwie zalety tego podejścia — po pierwsze, używanie funkcji staje się łatwiejsze, ponieważ nie musimy się już martwić o kolejność, a po drugie, możemy nadać wartości jedynie tym parametrom, którym chcemy, pomijając po drodze te, których domyślne wartości wolimy zostawić w spokoju.

Przykład (zapisz jako function_keyword.py):

def func(a, b=5, c=10):
    print('a is', a, 'and b is', b, 'and c is', c)

func(3, 7)
func(25, c=24)
func(c=50, a=100)

Rezultat:

$ python function_keyword.py
a is 3 and b is 7 and c is 10
a is 25 and b is 5 and c is 24
a is 100 and b is 5 and c is 50

Jak to działa:

Ta funkcja posiada jeden parametr bez domyślnej wartości i dwa, które ją posiadają.

Za pierwszym razem wpisujemy func(3, 7), dzięki czemu parametr a dostaje wartość 3, parametr b dostaje 7, a parametr c domyślną wartość 10.

Za drugim razem wpisujemy func(25, c = 24), więc parametr a otrzymuje wartość 25 (zgodnie z kolejnością), zaś parametr c dostaje 24, dzięki słowu kluczowemu. Parametr b ma domyślną wartość 5.

Za trzecim razem wpisujemy func(c = 50, a = 100) używając jedynie słów kluczowych. Zauważ, że przypisujemy wartość najpierw parametrowi c, niezależnie od tego, że parametr a występuje wcześniej (przed c) w deklaracji funkcji.

Dowolna ilość parametrów (VarArg)

Czasami chcesz zdefiniować funkcję która bierze dowolną ilość parametrów (variable number of arguments), można to uzyskać przez używanie gwiazdek (zapisz jako function_varargs.py):

def total(a=5, *numbers, **phonebook):
    print('a', a)

    #przechodzi przez wszystkie elementy w krotce
    for single_item in numbers:
        print('single_item', single_item)

    #przechodzi przez wszystkie elementy w słowniku   
    for first_part, second_part in phonebook.items():
        print(first_part,second_part)

print(total(10,1,2,3,Jack=1123,John=2231,Inge=1560))

Rezultat:

$ python function_varargs.py
a 10
single_item 1
single_item 2
single_item 3
Inge 1560
John 2231
Jack 1123
None

Jak to działa

Gdy deklarujemy parametr z gwiazdką np. *param, wtedy wszysztkie pozycyjne argumenty od tego miejsca są zbierane do krotki nazwanej param.

Podobnie, gdy deklarujemy parametr z podwójną gwiazdką np. **param, wtedy wszyzstkie argumenty kluczowe od tego miejsca są zbierane jako słownik nazwany param.

Więcej na temat krotek i słowników jest w poźniejszym rozdziale.

Wyrażenie return

Wyrażenia return używamy do wyjścia z funkcji. Możemy opcjonalnie zwrócić w tym momencie jakąś wartość.

Przykład (zapisz jako function_return.py):

def maximum(x, y):
    if x > y:
        return x
    elif x == y:
        return 'The numbers are equal'
    else:
        return y

print(maximum(2, 3))

Rezultat:

$ python function_return.py
3

Jak to działa:

Funkcja maximum wyszukuje maksymalną wartość spośród podanych. Używa w tym celu prostej konstrukcji if...else a następnie zwraca tę wartość dzięki poleceniu return.

Zauważ, że użycie wyrażenia return bez wartości jest równoznaczne z użyciem return None. None to specjalny typ w Pythonie, który reprezentuje po prostu nic. Używa się tego na przykład, gdy się chce przekazać, że zmienna nie ma wartości.

Każda funkcja domyślnie otrzymuje na końcu return None, chyba że napiszesz własne return. Możesz to sprawdzić uruchamiając print(some_function()) gdzie funkcja some_function nie używa wyrażenia return w ten sposób:

def some_function():
    pass

Wyrażenie pass wskazuje na pusty blok wyrażeń.

Uwaga
W Pythonie istnieje wbudowana funkcja max, która znajduje maksimum, więc możesz używać jej, zamiast pisać własną.

DocString

Python posiada sprytną funkcję zwaną documentation strings (po polsku wpisy dokumentacji — przyp. tłum.) znaną też pod skrótem docstrings. Jest to potężne narzędzie, którego powinieneś często używać, gdyż pomaga w lepszej organizacji programu oraz ułatwia zrozumienie jego działania. Dodatkowo możemy nawet odzyskać ten wpis z, powiedzmy, funkcji, gdy program jest uruchomiony!

Przykład (zapisz jako function_docstring.py):

def print_max(x, y):
    '''Wypisuje maksymalną liczbę spośród dwóch podanych.

    Obydwie wartości muszą być liczbami całkowitymi.'''
    # Zmienia na liczby całkowite, jeżeli to możliwe.
    x = int(x)
    y = int(y)

    if x > y:
        print(x, 'is maximum')
    else:
        print(y, 'is maximum')

print_max(3, 5)
print(print_max.__doc__)

Rezultat:

$ python function_docstring.py
5 is maximum
Wypisuje maksymalną liczbę spośród dwóch podanych.

    Obydwie wartości muszą być liczbami całkowitymi.

Jak to działa:

Tekst w pierwszej logicznej linijce funkcji to jej docstring (wpis dokumentacji). Pamiętaj, że wpisy mogą odnosić się również do modułów oraz klas, o czym powiemy sobie w odpowiednich rozdziałach.

Według układu stosowanego we wpisach, docstring to wielolinijkowy tekst, w którym pierwsza linijka zaczyna się dużą literą i kończy kropką. Druga linijka jest pusta, a od trzeciej zaczynają się dokładniejsze wyjaśnienia. Zdecydowanie radzę ci stosować się do tego układu w każdym wpisie w każdej twojej niebanalnej funkcji.

Możemy dostać się do wpisu funkcji print_max używając atrybutu __doc__ (zauważ podwójne podkreślenia). Pamiętaj, że Python traktuje wszystko jak obiekty, nawet funkcje. Dowiemy się więcej o obiektach w rozdziale dotyczącym klas.

Jeżeli używałeś już help() w Pythonie, to już zauważyłeś użycie wpisów. To polecenie po prostu wyciąga z funkcji to, co atrybut __doc__ i podaje w trochę bardziej eleganckiej formie. Możesz to wypróbować na swojej funkcji, po prostu wpisz w swoim programie help(print_max). Nie zapomnij, że z help wychodzi się naciskając klawisz q.

W taki sposób automatyczne narzędzia mogą uzyskać wpis z twoich programów, dlatego szczególnie zalecam ci umieszczanie wpisu w każdej twojej niebanalnej funkcji.

Podsumowanie

Poznaliśmy mnóstwo aspektów funkcji, ale oczywiście jest ich o wiele więcej. Pomimo to, zobaczyliśmy większość z tego, co bywa potrzebne podczas standardowego, codziennego używania Pythonowych funkcji.

W kolejnym rozdziale dowiemy się, jak używać i tworzyć moduły w Pythonie.

results matching ""

    No results matching ""