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]