Funkce a způsoby předávání parametrů

Jython, i když je objektově orientovaný, nepodporuje přetěžování funkcí. Toto je vynahrazeno širokou paletou možností, jak předávat parametry. Tyto, níže popsané vlastnosti, Java nepodporuje.

Funkce s nepovinnými argumenty

Kromě standardního způsobu definování funkce, je možné funkci definovat s proměnným počtem argumentů tak, že pro nepovinné argumenty nadefinujeme jejich defaultní hodnoty.

def fceNepovArg(x, a=2, b='treti'):
    print x, a, b

Způsoby volání výše definované funkce jsou následující:

>>> fceNepovArg(0)
0 2 treti
>>>
>>> fceNepovArg(0, 111)
0 111 treti
>>>
>>> fceNepovArg(0, 'Ahoj')
0 Ahoj treti
>>>
>>> fceNepovArg(0, a='Cau')
0 Cau treti
>>>
>>> fceNepovArg(0, b='III')
0 2 III
>>>
>>> fceNepovArg(x=0, a=123, b='III')
0 123 III

Výrazy definující defaultní hodnoty nepovinných parametrů, se nevyhodnocují při každém volání funkce, ale pouze jednou, a to tehdy, když je vykonáván příkaz definice funkce.

>>> a = 1
>>>
>>> def f(x = a):       #zacatek definice funkce
...     print x
...
>>>
>>> f()                 #pouziju defaultni hodnotu
1
>>>
>>> f(123)              #zadam svoji hodnotu
123
>>>
>>> a = 999
>>> f()                 #defaultni hodnota pouzije puvodni hodnotu
1
>>>

Volitelný seznam argumentů

Pokud je seznam argumentů ukončen argumentem, který obsahuje jako první znak *,  například *volitelny, pak argument obdrží tuple obsahující všechny přebývající parametry při volání funkce:

>>> def f(x, a='druhy', *volitelne):
...     print x, a, volitelne
...
>>>
>>> f(1)
1 druhy ()
>>>
>>>
>>> f(1,2)
1 2 ()
>>>
>>>
>>> f(1,2, 3, 4)
1 2 (3, 4)
>>>
>>> f(1, 'backora', 999, 'konec')
1 backora (999, 'konec')

Definice funkce, která může obsahovat libovolný počet argumentů, ale nemusí mít žádný, může začínat takto:

>>> def fce(*params):
...     print params
...
>>> fce()
()
>>>
>>> f('a', [1,2,3], {1: "ichi", 2: "ni"})
('a', [1, 2, 3], {2: 'ni', 1: 'ichi'})
>>>

Konečná syntaxe definice funkce je následující:

def nazevFunkce([arg, …[, *zbytek[, **argKlicSlov]]])
blok

Následující příklad osvětlí význam posledního typu parametru, který, pokud jej chceme použít, musí následovat za volitelným parametrem *zbytek.

>>> def f(a, b=0, c='ahoj', *d, **e):
...     print a, b, c, d, e
...
>>> f(1)
1 0 ahoj () {}
>>>
>>> f(1, 111)
1 111 ahoj () {}
>>>
>>> f(1, 2, 3, 4, 5, 6)
1 2 3 (4, 5, 6) {}
>>>
>>> f(1, 2, 3, typ='Wokenice', program='Wod Bila')
1 2 3 () {'program': 'Wod Bila', 'typ': 'Wokenice'}
>>>
>>> f(1, 2, 3, 4, 5, typ='Wokenice', program='Wod Bila')
1 2 3 (4, 5) {'program': 'Wod Bila', 'typ': 'Wokenice'}
>>>

Funkcionální programování

Ukázky kódu, se kterými jsme se doposud setkávali, byly psány způsobem blízkým procedurálnímu programování. Na Jythonu je sympatické, že vám nevnucuje, jakým způsobem máte své programy psát. Můžete používat procedurální způsob, objektově orientovaný způsob či funkcionální.

Lambda výrazy

Klíčové slovo lambda vám umožní vytvářet malé anonymní funkce. Termín lambda výraz je výstižný, neboť lambda výraz nesmí obsahovat příkazy. Syntaxe lambda výrazu je následující:

lambda seznam_parametru: vyraz

Ukažme si rozdíl mezi procedurálním a funkcionálním způsobem naprogramování funkce, která nám řekne, zda její argument je liché či sudé číslo:

>>># proceduralni zpusob programovani
>>>
>>> suda_licha(cislo):
...     if cislo%2:
...         return 'licha'
...     else:
...         return 'suda'
...
>>> suda_licha(6)
'suda'
>>>
>>> suda_licha(3)
'licha'
>>>
>>>############################################
>>># vyuziti lambda vyrazu
>>>
>>> suda_licha = lambda cislo: cislo % 2 and "licha" or "suda"
>>>
>>> suda_licha(6)
'suda'
>>> suda_licha(3)
'licha'
>>>
>>>
>>>############################################
>>>coz lze take zapsat takto
>>>
>>> suda_licha(cislo):
...     return cislo % 2 and "licha" or "suda"
...
>>> suda_licha(6)
'suda'
>>>
>>> suda_licha(3)
'licha'
>>>

Seznam argumentů pro lambda výrazy má stejné vlastnosti, jako v případě uživatelsky definovaných funkcí.

>>>#funkce vrati definici funkce, kterou pouziju dale
>>> def objemValce(vyska):
...     return lambda r, pi=3.14, vyska=vyska: pi*r**2 * vyska
...
>>> #zajimaji me objemy valce s ruznym polomerem a s vyskou 10
>>> objemy_pri_vysce_10 = objemValce(10)
>>>
>>> for r in range(1, 6):
...     print 'polomer:', r, 'objem:', objemy_pri_vysce_10(r)
...
polomer: 1 objem: 31.400000000000002
polomer: 2 objem: 125.60000000000001
polomer: 3 objem: 282.6
polomer: 4 objem: 502.40000000000003
polomer: 5 objem: 785.0

>>>

Protože lambda výrazy nemohou obsahovat příkazy (jako např. if/else, …), často se v nich používají operátory and/or pro implementaci logiky vyhodnocování výrazů.

>>> faktorial = lambda cislo: cislo==1 or cislo * faktorial(cislo-1)
>>> faktorial(5)
120

Lambda funkce se jeví jako účinný nástroj ve spolupráci s dalšími funkcemi definovanými v Jythonu. Příkladem může být funkce filter, kterou lze výhodně použít při práci se seznamy. Její syntaxe je následující:

filter(nazev_funkce, seznam)

Tuto funkci obecně použijete tam, kde potřebujete ze seznamu vybrat prvky na základě určitého kritéria.

>>> #suda cisla ze seznamu
>>> filter(lambda x: x%2 == 0, range(10))
[0, 2, 4, 6, 8]

Závěrem si ukažme hezký příklad použití funkce filter, kterým je úloha najití průniku dvou množin:

>>> set1 = range(0,200, 7)
>>> set2 = range(0,200, 3)
>>>
>>> filter(lambda x: x in set1, set2)
[0, 21, 42, 63, 84, 105, 126, 147, 168, 189]