Vytváření funkcí

Definice funkce

Funkce se definuje pomocí klíčového slova def.

def nazev_funkce (parametry,...):
                tělo funkce

Za dvojtečkou následuje blok – tělo funkce. Pokud je v tělu funkce příkaz return, pak se v tomto místě funkce ukončí a pokračuje se dalšími příkazy za místem, kde byla funkce volána. Pokud je za slovem return nějaký výraz, stane se návratovou hodnotou funkce. Jinak vrací funkce implicitně hodnotu None.

Příklad definice a použití funkce:

>>>def mocnina(x):
...     return x*x
...
>>> mocnina(2)
4

Funkce je také objektem. Její platnost začíná její definicí, můžete jí přiřadit do proměnné (tím jí přídělit nové jméno), nebo jí zrušit příkazem del.

>>> square = mocnina
>>> del mocnina
>>> square(3)
9
>>> mocnina(3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'mocnina' is not defined
V Pythonu to nefunguje tak jak například v PHP nebo JavaScriptu, kde můžete funkci volat ve zdrojovém kódu dříve, než je uvedena její definice.

Parametry funkce

Funkce může mít žádný, jeden, mnoho, nebo proměnlivý počet parametrů.

Jelikož je Python beztypový jazyk, neuvádí se ani typy parametrů funkce. I pokud vytvoříte funkci, která nepoužívá žádný parametr, nesmíte zapomenout na závorky za jménem funkce. První tři případy jsou triviální, proto ukáži jen funkci s proměnlivým počtem argumentů.

Argumenty, jejichž počet dopředu neznáme se ukládá do proměnné označené hvězdičkou jako n-tice. Proměnná s * je vždy až za všemi ostatními „normálními“ parametry.

>>> def vypis(zacatek, *ntice):
        print(type(ntice))
        citac = zacatek
        for i in ntice:
            citac = citac + 1
            print("%2i:" % citac, i)

>>> vypis(5,'1','dva',3,'4')
<class 'tuple'>
 6: 1
 7: dva
 8: 3
 9: 4

Implicitní hodnoty parametrů

Implicitní hodnoty parametrů jsou příjemnou součástí moderních programovacích jazyků, jako například C++. Python není vyjímkou.

Implicitní hodnota se parametrům přiřadí v definici funkce pomocí =. Pokud se volá funkce, která obsahuje implicithní hodnoty pro některé parametry, nemusí se za tyto parametry s implicitní hodnotou dosazovat.

Vpravo od implicitního parametru mohou být již jen parametry s implicitní hodnotou. Při volání funkce se objekty dosazují nejdříve do parametrů bez implicitních hodnot a poté do parametrů s implicitními hodotami (postupuje se zleva do prava). Z toho vyplívá, že chcete-li dosadit za implicitní parametr, musíte dosadit za všechny parametry vlevo od něj. Nebo použít použít jména parametrů (viz dále).

>>> def mocnina(x, y=2, format=0):
...     x = x**y
...     if not format:
...             return x
...     else:
...             return "({0})".format(x)
...
>>> print(mocnina(2), mocnina(2, 3), mocnina(2, 2, True))
4 8 (4)

A jeden chytáček: implicitní argumenty se přiřazují jen jednou. To znamená, že při použití implicitního argumetnu při každém volání funkce používáte tu samou proměnnou. Což se může někdy hodit a někdy ne. V příkladu níže se to hodí.

>>> def fronta(add=None,f=[]):
...     if(add == None):
...         return f.pop()
...     f.insert(0,add)
...     print(f)
...
>>> fronta('a')
['a']
>>> fronta('b')
['b', 'a']
>>> fronta('c')
['c', 'b', 'a']
>>> fronta()
'a'    
>>> fronta()
'b'    

Jména parametrů

Nechcete-li přemýšlet, v jakém pořadí jsou zapsány parametry v definici funkce, můžete je volat s jejich jmény. Tato možnost se také hodí pro implicitní parametry, chcete-li přiřadit hodnotu implicitnímu parametru a přitom nepřiřazovat hodnoty všem implicitním parametrům vlevo od něj.

>>> def funkce(a, b, c='c', d='d', e=None, f=''):
...     print(a, b, c, d, e)
...
>>> funkce(b='b', a='A', e='E')
A b c d E
>>> funkce('A', e='E', b='b')
A b c d E
>>> funkce(a='A', e='E')     # chyba - není předán parametr b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: funkce() missing 1 required positional argument: 'b'
Parametry, které nemají implicitní hodnotu, se musí při volání funkce předat.

V předcházejícím příkladě s mocninou bychom si při třetím volání funkce mohli ušetřit vyplňování druhého argumentu.

>>> mocnina(2,format=1)
'(4)'

Proměnlivý počet parametrů

Pokud dopředu nevíte kolik předáte funkci argumentů, můžete použít parametr s hvězdičkou (varadic argument). Ten bude obsahovat argumenty, které bude funkce obsahovat „navíc“ oproti obyčejným argumentům a argumentům s implicitní hodnotou, které jsou deklarovány před argumentem s hvězdičkou.

Argument s hvězdičkou musí být uveden až za parametry bez implicitní hodnoty. Argumenty s implicitní hodnotou, které jsou v definici funkci až za argumentem s hvězdičkou, nelze předat funkci jinak než jako pojmenovaný argument.

>>> def moje_fce(a, b, c=5, *ostatni, d='ddd'):
...     print(a, b, c, d)
...     print(ostatni)
...
>>> moje_fce(3, 4)
3 4 5 ddd
()
>>> moje_fce(3, 4, 5, 6, 7)
3 4 5 ddd
(6, 7)
>>> moje_fce(3, 4, 5, 6, 7, d='D')
3 4 5 D
(6, 7)

Poslední parametr může být parametr s dvěma hvězdičkami. Tam se přiřazují všechny argumenty, které jsou předány funkci „navíc“ jako pojmenované argumenty.

Předané hodnoty jsou uloženy do argumentu ve formě slovníku, kde klíč je jméno argumentu a hodnota je hodnota předaná argumentu.

Tento parametr musí být uveden jako poslední.

>>> def moje_fce(a, b, c=5, *ostatni, **ostatni_pojmenovane):
     print(a, b, c)
     print(ostatni)
     print(ostatni_pojmenovane)
...
>>> moje_fce(3, 4)
3 4 5
()
{}
>>> moje_fce(3, 4, 5, 6, 7)
3 4 5
(6, 7)
{}
>>> moje_fce(3, 4, 5, 6, x=7)
3 4 5
(6,)
{'x': 7}
>>> moje_fce(b=3, a=4, f=5, c=6, x=7)
4 3 6
()
{'f': 5, 'x': 7}

Rozbalování argumetnů

Tato podivně pojmenovaná část je o tom, jak předat jako argumenty hodnoty uložené v seznamu (nebo listu) a slovníku.

Pokud předáte seznam nebo slovník jen svým jménem, předají se jako jeden argument. Pomocí hvězdičky nebo dvou je můžete rozbalit, jako byste jednotlivé hodnoty seznamu rozepsali do argumetnů volané funkce. U slovníků to navíc funguje jako pojmenované argumenty.

>>> def test(a, b, c=0, d=0, *zbytek, **pojmenovane):
...     print(a, b, c, d)
...     print(zbytek)
...     print(pojmenovane)
...
>>> seznam = ['a','b','c','d']
>>> slovnik = {'d' : 'DDD','e' :'EEE'}
>>> test(3,4)
3 4 0 0
()
{}
>>> test(slovnik, seznam)    #slovnik odpovida jednomu argumentu (a) a seznam druhemu (b)
{'e': 'EEE', 'd': 'DDD'} ['a', 'b', 'c', 'd'] 0 0
()
{}
>>> test(*slovnik)  # klíče slovníku se použijí jako nepojmenované argumenty, viz poznámka 1)
e d 0 0
()
{}
>>> test(*seznam)
a b c d
()
{}
>>> test(**slovnik)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: test() missing 2 required positional arguments: 'a' and 'b'
>>> test('a','b',**slovnik)
a b 0 DDD
()
{'e': 'EEE'}
>>> test('a','b',**seznam)  # chyba - ** lze aplikovat jen na slovník
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: test() argument after ** must be a mapping, not list
1) Všimněte si, že použití slovníku s jednou hvězdičkou je velmi nevděčné. Jednak se nepoužijí jeho hodnoty ale klíče a druhak, protože ve slovníku není zaručeno žádné seřazení, nemusí to vždy dopadnout tak, že první klíč bude předán jako první argument atd. …

Lokální versus globální proměnné

Teď je na čase si připomenou Jmenný prostor. Funkce si vytvářejí také svůj lokální jmenný prostor. Každé přiřazení do proměnné uloží hodnotu do tohoto lokálního jmenného prostoru a neovlivní tak ten globální (což je super). Pokud se na nějakou proměnnou odvoláváte (jejím jménem, jak jinak), pak se hledá v tomto lokálním jmenném prostoru. Pokud se tam nenajde, hledá se ve jmenném prostoru funkce, která danou funkci volala … a tak to pokračuje, až se dostanete do globálního jmenného prostoru. Pokud se jméno proměnné (nebo funkce, třídy …) nenajde ani tam, pak teprve dojde k výjimce NameError.

Lokálně vytvořené proměnné (uvnitř těla funkce) po skončení funkce zanikají.

Pokud chcete přeci jen přiřadit hodnotu nějaké globální proměnné, můžete použít klíčové slovo global. Proměnná, do které se přiřazuje se pak začne hledat v nadřazené funkci, ještě nadřazenější funkci … až v globálním jmenném prostoru. Pokud se nenajde ani tam, tak se v globálním jmenném prostoru vytvoří (žádná chyba).

>>> x = 'globalni promenna'
>>> 'x' in dir()           # proměnná 'x' je součástí globálního jmenného prostoru
True
>>> def test():
...     x = 'localni promenna'
...     y = 'localni promenna'
...     global z
...     z = 'globalni'
...
>>> test()
>>> print(x, z)
('globalni promenna', 'globalni')
>>> 'y' in dir()          # proměnná 'y' se do globálního jmenného prostoru nedostala
False
>>> print(y)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'y' is not defined

Jeden programátorský oříšek, který by vás mohl zaskočit:

  1. >>> x = 'globalni promenna'
  2. >>> def test1():
  3. ...    print(x)
  4. ...
  5. >>> test1()
  6. globalni promenna
  7. >>> def test2():
  8. ...    print(x)
  9. ...    x = 'localni'
  10. ...    print(x)
  11. ...
  12. >>> test2()
  13. Traceback (most recent call last):
  14.   File "<stdin>", line 1, in <module>
  15.   File "<stdin>", line 2, in test2
  16. UnboundLocalError: local variable 'x' referenced before assignment

Funkce test1() používá globální proměnnou, na tom není nic divného. Ovšem funkce test2() už na řádku 8 bere x jako lokální proměnnou, kvůli přiřazení na řádku 9. Pokud jste čekali, že Python vyhodnotí na řádku 8 x jako globální proměnnou a až na řádku 10 jako lokální, pak je to 1:0 pro Python :-). Python si totiž nejdřív pročte celý blok, zapamatuje si všechny lokální proměnné (s nepřiřazenou hodnotou), jako byste je všechny deklarovali na začátku bloku.

Komentář Hlášení chyby
Created: 11.9.2005
Last updated: 30.8.2015
Tato stánka používá ke svému běhu cookies, díky kterým je možné monitorovat, co tu provádíte (ne že bych to bez cookies nezvládl). Také vás tu bude špehovat google analytics. Jestli si myslíte, že je to problém, vypněte si cookies ve vašem prohlížeči, nebo odejděte a už se nevracejte :-). Prohlížením tohoto webu souhlasíte s používáním cookies. Dozvědět se více..