Syntaktický cukr

Jako syntaktický cukr (syntactic sugar) je označení syntaktických konstrukcí jazyka, které by šli zapsat běžnou syntaxí, ale syntaktický cukr je další, obvykle kratší a přehlednější formou zápisu.

Zjednodušený cyklus (vytváření seznamů)

Uvažujte následující příklad inicializace seznamu:

>>> squares = []
>>> for x in range(10):
...     squares.append(x**2)
...
>>> squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Nešlo by to nějak stručněji? Šlo:

>>> [x**2 for x in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Tento zkrácený zápis může být i vnoření cyklus a mít na konci podmínku if. Pokud není podmínka if splněna, do výsledného seznamu (listu …) se hodnota/výraz nedostane.

>>> [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y)]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

Další příklad transponuje matici (resp. seznam seznamů).

>>> matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
>>> [[row[i] for row in matrix] for i in range(4)]
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

Obdobně to jde i s typem set:

>>> {x for x in 'abracadabra' if x not in 'abc'}
{'r', 'd'}

A nebo se slovníkem:

>>> {x: x**2 for x in (2, 4, 6)}
{2: 4, 4: 16, 6: 36}

A nebo s n-ticí:

>>> (x**2 for x in range(10))
<generator object <genexpr> at 0xb7303144>

A ejhle, ona se nevytvořila n-tice, ale jakýsi generátor. Vzpomeňte si na funkci (x)range(), která vracela typ 'range'. Zde to má význam stejný – šetří se paměť počítače.
Vytvoření generátoru dává vcelku u neměnitelné n-tice smysl (narozdíl od měnitelného seznamu).

Bacha na to, že do tohoto generátoru nelze přistupovat pomocí indexů. Pokud byste něco takového potřebovali, není nic snazšího než převést generátor na n-tici:

>>> g = (x**2 for x in range(10))
>>> n = list(g)
>>> n[4]
16
>>> g[4]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'generator' object is not subscriptable

Lambda funkce

Klíčové slovo lambda se používá pro vytvoření nepojmenovaných funkcí. Hodí se v případech, kde chcete vytvořit funkci „na jedno použití“. Tedy tam, kde by jste normálně definovali funkci (pomocí def), pak ji jednou použili a zase smazali.

Tělo lambda funkce je omezené na jeden výraz. Takže jako lambda funkce není možné psát nic extra složitého.

Za klíčové slovo lambda se píší jména argumentů (nejsou v závorce), pak dvojtečka a pak výraz, který je zároveň tělem i návratovou hodnotou lambda funkce.

>>> lambda x:  x + 1
<function <lambda> at 0xb72fd8b4>
>>> def inc(x):
...     return x + 1
...
>>> inc(5)
6
>>> inc = lambda x: x + 1
>>> inc(5)
6

Funkce vytvořené uvnitř jiné funkce mají přístup k lokálním proměnným funkce, která je vytváří. Toho se dá využít. Pokud funkci vrátíte jako návratovou hodnotu, lokální proměnné vytvářející funkce budou stále s vytvořenou funkcí svázány (funguje to podobně jako v JavaScriptu, jestli to znáte).

>>> def uzavorkovavac(start, end):
...     return lambda *hodnoty: "{}{}{}".format(start, " ".join(hodnoty), end)
...
>>> u = uzavorkovavac('{', '}')
>>> u('a', 'b', 'c')
'{a b c}'
>>> h1 = uzavorkovavac('<h1>', '</h1>') # nove volani fce uzavorkovavac() -> nove lokalni promenne
>>> h1('zdar')
'<h1>zdar</h1>'
>>> u('zdar')          # porad pristupuje k puvodnim lokalnim promennym start a end
'{zdar}'
>>>

Zdůrazňuji, že tato vlastnost s uchováváním odkazů na lokální proměnné nadřazené funkce se netýkají jen lambda funkcí, ale i funkcí definovaných pomocí def (definovaných uvnitř jiné funkce). Použití lambda je opravdu jen syntaktický cukr.

Komentář Hlášení chyby
Created: 15.5.2013
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..