Obsah
1. Práce s nekonečnými sekvencemi v knihovně funcy
2. Konečná sekvence se stejnými hodnotami vytvořená pomocí repeat
3. Nekonečná sekvence se stejnými hodnotami vytvořená pomocí repeat
4. Dá se vůbec reálně pracovat s nekonečnými sekvencemi?
5. Aritmetická řada generovaná pomocí count
6. Specifikace počáteční hodnoty a kroku
7. Čím se vlastně odlišuje count od range?
8. Příklady použití aritmetické řady
9. Sekvence s opakujícími se cykly hodnot generovaná pomocí cycle
10. Nekonečná sekvence sudých a lichých čísel
11. Sekvence obsahující označení všech hracích karet
12. Nekonečná sekvence s hodnotami vytvářenými s využitím uživatelské funkce
13. Číselné řady a další sekvence generované s využitím iterate
14. Vygenerování Fibonacciho posloupnosti s využitím iterate
15. Další užitečné funkce používané při zpracování sekvencí
16. Rozdělení prvků sekvence do skupin funkcí group_by
17. Rozdělení slov podle jejich délky
18. Kombinace většího množství sekvencí s využitím funkce interleave
19. Repositář s demonstračními příklady
1. Práce s nekonečnými sekvencemi v knihovně funcy
V dnešním článku se zaměříme na popis práce s nekonečnými sekvencemi s využitím generátorů a funkcí poskytovaných knihovnou funcy. Nekonečné sekvence jsou zajímavé v mnoha ohledech, například proto, že se u nich do značné míry stírá rozdíl mezi daty (klasicky chápanými jako množina statických hodnot) a dynamickým kódem. Ovšem zajímavé je i to, že při práci s nekonečnými sekvencemi je nutné využívat funkcionální paradigma, tedy například funkce vyššího řádu, referenčně transparentní funkce, uzávěry, memoizaci atd. Nositelem hodnot jsou zde skutečně funkce a nikoli statická sekvence dat (n-tice, seznamy atd.).
V navazujících kapitolách si popíšeme následující generátory nekonečných sekvencí:
| Funkce/generátor | Stručný popis | Kapitola |
|---|---|---|
| repeat | sekvence stejných hodnot | 2 |
| count | řada numerických hodnot (aritmetická řada) | 5 |
| cycle | sekvence tvořená několika opakujícími se hodnotami | 9 |
| iterate | sekvence, u níž je následující prvek vytvořen transformací hodnoty předchozího prvku | 13 |
2. Konečná sekvence se stejnými hodnotami vytvořená pomocí repeat
První funkcí, která slouží jako generátor konečné nebo nekonečné sekvence, je funkce nazvaná příznačně repeat. Této funkci se předává jeden povinný parametr – hodnota, která se bude v sekvenci opakovat. Druhý parametr je nepovinný a určuje počet prvků sekvence. V případě, že počet prvků není explicitně stanoven, vznikne nekonečná sekvence.
Podívejme se nyní na způsob vygenerování konečné sekvence, konkrétně sekvence deseti celočíselných hodnot 42:
from funcy import repeat values = repeat(42, 10) print(values)
Výsledkem (který se zobrazí na terminálu) je generátor sekvence, nikoli přímo hodnoty v sekvenci:
repeat(42, 10)
Pro získání hodnot (nebo obecně prvků) uložených v sekvenci musíme sekvenci materializovat (což je nepřesný překlad termínu realize), například jejím explicitním převodem na seznam:
from funcy import repeat values = repeat(42, 10) print(list(values))
Výsledkem nyní skutečně bude seznam s deseti celočíselnými hodnotami 42:
[42, 42, 42, 42, 42, 42, 42, 42, 42, 42]
3. Nekonečná sekvence se stejnými hodnotami vytvořená pomocí repeat
V případě, že se funkce repeat zavolá jen s jediným parametrem, bude tento parametr chápaný jako hodnota prvků, která se bude v sekvenci opakovat do nekonečna. V případě, že se nepokusíme celou sekvenci materializovat, je možné s takovou sekvencí bez problémů pracovat, protože k výpočtu (všech) prvků nedochází. Ostatně si to můžeme snadno vyzkoušet na následujícím příkladu:
from funcy import repeat values = repeat(42) print(values)
Výsledkem činnosti tohoto skriptu bude objekt, který dokáže produkovat prvky nekonečné sekvence:
repeat(42)
Ovšem samotná materializace celé nekonečné sekvence nemůže (podle očekávání) dopadnout dobře:
from funcy import repeat values = repeat(42) print(list(values))
Tento příklad se pokusí o převod všech prvků nekonečné sekvence na seznam, což po jisté době skončí s chybou – nelze alokovat dostatek paměti.
4. Dá se vůbec reálně pracovat s nekonečnými sekvencemi?
Na tomto místě je vhodné se ptát, jak a zda je vůbec možné pracovat s nekonečnými sekvencemi, které pochopitelně není možné celé materializovat. Ve skutečnosti je práce s takovými sekvencemi v některých případech poměrně elegantní. Nejprve se ale podívejme na poněkud umělý příklad, v němž nejdříve vytvoříme nekonečnou sekvenci a následně z této sekvence získáme prvních dvacet prvků. Tuto – nyní již konečnou – sekvenci je již možné bez problému převést na seznam a tak ji materializovat:
from funcy import repeat, take values = repeat(42) slice = take(20, values) print(list(slice))
Výsledek by měl vypadat následovně:
[42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42]
K samotnému výpočtu prvků může ve skutečnosti dojít až při převodu na seznam, tedy v posledním příkazu.
Zkusme si nyní vytvořit nepatrně složitější příklad, v němž dochází ke kombinaci konečné sekvence vygenerované standardní funkcí range a nekonečné sekvence vytvořené funkcí repeat z knihovny Funcy. Tyto dvě sekvence „zazipujeme“ s využitím standardní funkce zip, přičemž výsledkem bude sekvence dvojic – a to konečná sekvence, protože počet prvků určuje kratší vstup; tedy v tomto případě sekvence vytvořená pomocí range (druhým vstupem je nekonečná sekvence):
from funcy import repeat values1 = range(10) values2 = repeat(42) zipped = zip(values1, values2) print(list(zipped))
Výsledek je konečný a můžeme ho tedy bez problémů vypsat na terminál:
[(0, 42), (1, 42), (2, 42), (3, 42), (4, 42), (5, 42), (6, 42), (7, 42), (8, 42), (9, 42)]
5. Aritmetická řada generovaná pomocí count
Další typ nekonečné sekvence je generován s využitím funkce nazvané count. Jak již název této funkce naznačuje, slouží k vytvoření sekvence s postupně rostoucími či klesajícími hodnotami čítače, přičemž s využitím nepovinných parametrů je možné specifikovat jak počáteční hodnotu čítače (start, výchozí hodnotou je nula), tak i krok (step, výchozí hodnota je rovna jedné).
Nekonečná sekvence 0, 1, 2, 3, … je vytvořena následovně:
from funcy import count values = count() print(values)
Výsledkem je podle očekávání „jen“ generátor sekvence, nikoli samotné hodnoty:
count(0)
V dalším demonstračním příkladu získáme prvních dvacet hodnot čítače z původně nekonečné sekvence:
from funcy import count, take values = count() slice = take(20, values) print(list(slice))
Nyní je sekvence materializována a má obsah:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
6. Specifikace počáteční hodnoty a kroku
Při definici nekonečné sekvence generované funkcí count je možné specifikovat hodnotu prvního prvku této sekvence, a to s využitím nepovinného parametru start:
from funcy import count, take values = count(start=10) slice = take(20, values) print(list(slice))
Nyní bude prvních dvacet prvků sekvence vypadat takto:
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]
Zadat lze i krok, tj. numerický rozdíl mezi dvěma po sobě jdoucími prvky. Implicitní hodnota kroku je rovna jedné, ovšem lze ji snadno modifikovat:
from funcy import count, take values = count(start=10, step=2) slice = take(20, values) print(list(slice))
Opět se podívejme na prvních dvacet prvků této nekonečné sekvence:
[10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48]
Krok ovšem může být i záporný:
from funcy import count, take values = count(start=0, step=-2) slice = take(20, values) print(list(slice))
Výsledky, tedy v tomto případě prvních dvacet prvků nekonečné sekvence:
[0, -2, -4, -6, -8, -10, -12, -14, -16, -18, -20, -22, -24, -26, -28, -30, -32, -34, -36, -38]
7. Čím se vlastně odlišuje count od range?
Až doposud by se mohlo zdát, že se generátor nekonečné sekvence count vlastně do značné míry podobá standardnímu generátoru range. Je zde ovšem několik důležitých rozdílů, například fakt, že count dokáže pracovat i s čísly s plovoucí řádovou čárkou a podobá se tak více spíše funkci arange z knihovny Numpy (ta ovšem generuje striktně konečnou sekvenci). Ostatně sami si můžeme vyzkoušet, že jak počáteční hodnota číselné sekvence, tak i krok mezi sousedními prvky nemusí být celočíselnými hodnotami:
from funcy import count, take values = count(start=0.5, step=1.5) slice = take(20, values) print(list(slice))
Nyní bude prvních dvacet prvků takto vygenerované nekonečné sekvence vypadat následovně:
[0.5, 2.0, 3.5, 5.0, 6.5, 8.0, 9.5, 11.0, 12.5, 14.0, 15.5, 17.0, 18.5, 20.0, 21.5, 23.0, 24.5, 26.0, 27.5, 29.0]
8. Příklady použití aritmetické řady
Již v předchozím textu jsme si ukázali kombinaci dvou konečných či nekonečných sekvencí s využitím standardní funkce zip, která vždy spojí dvojici prvků, z nichž první je vybrán z první sekvence a další ze sekvence druhé. Totéž pochopitelně můžeme udělat i v případě aritmetické řady generované funkcí count a sekvencí stejných prvků generovaných funkcí repeat. Druhá ze sekvencí má konečný počet prvků, takže i výsledkem aplikace zip bude konečná sekvence (dvojic):
from funcy import count, repeat values1 = count() values2 = repeat(42, 10) zipped = zip(values1, values2) print(list(zipped))
Výsledky:
[(0, 42), (1, 42), (2, 42), (3, 42), (4, 42), (5, 42), (6, 42), (7, 42), (8, 42), (9, 42)]
Zazipovat ovšem můžeme i nekonečné sekvence! Před tiskem takové sekvence je pochopitelně nutné omezit počet prvků, například s využitím take:
from funcy import count, repeat, take values1 = count() values2 = repeat(42) zipped = zip(values1, values2) slice = take(10, zipped) print(list(slice))
Výsledek:
[(0, 42), (1, 42), (2, 42), (3, 42), (4, 42), (5, 42), (6, 42), (7, 42), (8, 42), (9, 42)]
V případě potřeby lze získat ty prvky ze sekvence, které stojí před „zarážedlem“ (prvkem s nějakou vlastností testovanou predikátem):
from funcy import count, takewhile values = count() filtered = takewhile(lambda x:x<10, values) print(filtered) print(list(filtered))
Výsledky:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
9. Sekvence s opakujícími se cykly hodnot generovaná pomocí cycle
Dalším typem nekonečné sekvence, kterou je možné s využitím knihovny Funcy vytvořit, je sekvence, v níž se stále opakují stejné hodnoty. Taková sekvence se vytváří funkcí cycle, které se, například formou n-tice, seznamu nebo jiné sekvence, předají hodnoty, které se budou ve výsledné nekonečné sekvenci neustále opakovat. Vytvořme si tedy sekvenci, v níž se budou neustále opakovat hodnoty „foo“ a „bar“:
from funcy import cycle values = cycle(["foo", "bar"]) print(values)
Výsledkem bude tento objekt, který je generátorem sekvence:
<itertools.cycle object at 0x7fe288af42c0>
Samozřejmě můžeme z takové sekvence získat několik prvních hodnot a přesvědčit se o tom, jak taková sekvence vypadá v praxi. Pro přečtení prvních několika hodnot použijeme nám již velmi dobře známou funkci take:
from funcy import cycle, take values = cycle(["foo", "bar"]) slice = take(10, values) print(slice)
A takto vypadají výsledky:
['foo', 'bar', 'foo', 'bar', 'foo', 'bar', 'foo', 'bar', 'foo', 'bar']
10. Nekonečná sekvence sudých a lichých čísel
V dalším demonstračním příkladu zkombinujeme čtyři funkce, které již známe. Jedná se o generátory sekvencí count, cycle, zip a take. Necháme si vygenerovat sekvenci celých čísel a u každé hodnoty určíme, jestli se jedná o sudou nebo o lichou hodnotu. Bez jakýchkoli výpočtů (výpočet zbytku po dělení dvěma atd.) je možné celý algoritmus realizovat následujícím způsobem:
from funcy import count, cycle, take
values1 = count(start=1)
values2 = cycle(["odd", "even"])
zipped = zip(values1, values2)
slice = take(10, zipped)
for key, val in slice:
print(key, val)
Po spuštění tohoto skriptu by se na terminálu mělo zobrazit deset celočíselných hodnot a taktéž informace o tom, zda se jedná o sudou nebo naopak o lichou hodnotu:
1 odd 2 even 3 odd 4 even 5 odd 6 even 7 odd 8 even 9 odd 10 even
11. Sekvence obsahující označení všech hracích karet
Podívejme se ještě na jeden (poněkud umělý) příklad založený na funkci cycle, resp. přesněji řečeno na dvojici funkcí cycle. Vygenerujeme si sekvenci obsahující označení všech 52 francouzských karet. V imperativním kódu by bylo možné použít dvojici vnořených smyček, v klasickém Pythonním kódu pak generátorovou notaci. Realizace podobného algoritmu založeného na nekonečných sekvencích může vypadat takto:
from funcy import count, cycle, take
suits = ["♠", "♥", "♦", "♣"]
values = ["2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"]
seq1 = cycle(suits)
seq2 = cycle(values)
zipped = zip(seq1, seq2)
slice = take(len(suits)*len(values), zipped)
for key, val in slice:
print(f"{key}{val}")
Výsledek:
♠2 ♥3 ♦4 ♣5 ... ... ... ♣10 ♠J ♥Q ♦K ♣A
Otázky k zamyšlení? Skutečně se vygeneruje všech 52 unikátních kombinací, nebo budou mít některé karty stejnou hodnotu? A za jakých podmínek bude tento algoritmus fungovat korektně (počet barev atd.)?
12. Nekonečná sekvence s hodnotami vytvářenými s využitím uživatelské funkce
Nekonečné sekvence generované funkcemi repeat, count a cycle jsou sice užitečné, ale zdaleka nepokrývají všechny možné varianty. Poměrně často se setkáme s tím, že další prvek sekvence je možné odvodit (pouze) z prvku předchozího na základě nějakého výrazu či složitějšího výpočtu. Příkladem mohou být geometrické a další řady. V takovém případě lze pro vytvoření nekonečné sekvence použít funkci nazvanou příznačně iterate. Této funkci se zadává hodnota počátečního prvku v sekvenci a taktéž funkce, které se předá hodnota n-tého prvku a výsledkem bude hodnota prvku n+1. Výpočet prováděný v této funkci může být zcela obecný (a kromě běžné funkce můžeme samozřejmě použít i uzávěr).
13. Číselné řady a další sekvence generované s využitím iterate
Podívejme se na nejjednodušší možný příklad – generátor nekonečné aritmetické řady s krokem 1 a počátečním prvkem s nulovou hodnotou:
from funcy import iterate, take
def inc(x):
return x+1
sequence = iterate(inc, 0)
slice = take(10, sequence)
print(slice)
Výsledky:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Můžeme použít i alternativní způsob zápisu založeného na anonymní funkci:
from funcy import iterate, take sequence = iterate(lambda x: x+1, 0) slice = take(10, sequence) print(slice)
Výsledky by měly být totožné:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Ve třetím příkladu je ukázána řada numerických hodnot obsahujících celočíselné mocniny dvojky:
from funcy import iterate, take
def double(x):
return x*2
sequence = iterate(double, 1)
slice = take(10, sequence)
print(slice)
Výsledky:
[1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
Taktéž si můžeme vygenerovat sekvenci seznamů, v nichž postupně roste počet prvků (i jejich hodnoty):
from funcy import iterate, take
def nextval(x):
return x + [x[-1]+1]
sequence = iterate(nextval, [1])
slice = take(10, sequence)
print(slice)
Výsledky:
[[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6, 7], [1, 2, 3, 4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]
14. Vygenerování Fibonacciho posloupnosti s využitím iterate
Poněkud komplikovanější je výpočet Fibonacciho posloupnosti s využitím funkce iterate. Nyní totiž musíme pracovat s dvojicí prvků s indexy n-1 a n pro výpočet prvku s indexem n+1. To sice iterate přímo neumožňuje, ale lze zde aplikovat trik – budeme předávat dvojici hodnot v jediném parametru typu n-tice:
from funcy import iterate, take
def one_step(p):
return (p[1], p[0]+p[1])
sequence = iterate(one_step, (0, 1))
slice = take(10, sequence)
print(slice)
Výsledky ukazují, že sekvence bude obsahovat dvojice a první prvky tvoří jednu Fibonacciho řadu a druhé prvky řadu druhou (posunutou o jeden prvek):
[(0, 1), (1, 1), (1, 2), (2, 3), (3, 5), (5, 8), (8, 13), (13, 21), (21, 34), (34, 55)]
Nyní tedy máme k dispozici dvojice s hodnotami dvou Fibonacciho posloupností. Získání první posloupnosti je již snadné – aplikujeme funkci first na všechny prvky posloupnosti dvojic:
from funcy import first, iterate, take
def one_step(p):
return (p[1], p[0]+p[1])
sequence = iterate(one_step, (0, 1))
slice = take(20, sequence)
print(list(map(first, slice)))
Výsledkem již bude stará dobrá Fibonacciho posloupnost:
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181]
15. Další užitečné funkce používané při zpracování sekvencí
V knihovně Funcy nalezneme i další zajímavé a mnohdy i velmi užitečné funkce, které lze využít při práci s konečnými i nekonečnými sekvencemi. V navazujících kapitolách si popíšeme dvě takové funkce. První z nich se jmenuje group_by a druhá interleave. S využitím group_by je možné rozdělit prvky vstupní sekvence do několika (obecně mnoha) skupin na základě nějaké jejich vlastnosti (hodnoty atd.). A funkce interleave nám umožňuje zkombinovat prvky z několika sekvencí do sekvence jediné (což je operace, kterou lze provést i pro nekonečné sekvence, jak ostatně uvidíme dále).
16. Rozdělení prvků sekvence do skupin funkcí group_by
Funkce nazvaná group_by dokáže rozdělit původní sekvenci prvků do několika dalších sekvencí, přičemž rozdělení je prováděno na základě nějaké hodnoty vypočtené z každého prvku (na rozdíl od funkce filter či remove se zde tedy nejedná o predikát vracející pouze pravdivostní hodnotu). Příkladem může být rozdělení sekvence s celočíselnými hodnotami 0..99 do deseti sekvencí na základě poslední (nejnižší) cifry hodnoty. V jedné výsledné sekvenci tedy budou hodnoty končící na nulu, v další hodnoty končící na jedničku atd. (výsledkem je mapa, jak ostatně uvidíme dále):
from funcy import group_by
values = range(100)
grouped = group_by(lambda x:x % 10, values)
for key, values in grouped.items():
print(key, values)
Výsledek by měl vypadat následovně:
0 [0, 10, 20, 30, 40, 50, 60, 70, 80, 90] 1 [1, 11, 21, 31, 41, 51, 61, 71, 81, 91] 2 [2, 12, 22, 32, 42, 52, 62, 72, 82, 92] 3 [3, 13, 23, 33, 43, 53, 63, 73, 83, 93] 4 [4, 14, 24, 34, 44, 54, 64, 74, 84, 94] 5 [5, 15, 25, 35, 45, 55, 65, 75, 85, 95] 6 [6, 16, 26, 36, 46, 56, 66, 76, 86, 96] 7 [7, 17, 27, 37, 47, 57, 67, 77, 87, 97] 8 [8, 18, 28, 38, 48, 58, 68, 78, 88, 98] 9 [9, 19, 29, 39, 49, 59, 69, 79, 89, 99]
17. Rozdělení slov podle jejich délky
Funkci group_by můžeme použít například i pro seskupení slov v textu podle jejich délky. Text nejdříve rozdělíme na jednotlivá slova (resp. přesněji řečeno na sekvenci slov) a následně použijeme group_by, přičemž seskupení vstupních prvků bude vázáno na hodnotu vypočtenou výrazem len(prvek):
from funcy import group_by
message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
words = message.split()
grouped = group_by(lambda x:len(x), words)
for key, values in grouped.items():
print(key, values)
Výsledkem získaným po spuštění tohoto skriptu bude mapa obsahující jako klíče hodnoty len(prvek) a jako hodnoty sekvenci slov s touto délkou:
5 ['Lorem', 'ipsum', 'dolor', 'amet,', 'elit,', 'magna'] 3 ['sit', 'sed'] 11 ['consectetur'] 10 ['adipiscing', 'incididunt'] 2 ['do', 'ut', 'et'] 7 ['eiusmod'] 6 ['tempor', 'labore', 'dolore', 'aliqua']
Praktičtější však bude mapu při jejím výpisu setřídit, takže se nejdříve vypíšou nejkratší slova, potom delší slova atd.:
from funcy import group_by
message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
words = message.split()
grouped = group_by(lambda x:len(x), words)
for key in sorted(grouped.keys()):
print(key, grouped[key])
Nyní bude získaný výsledek (mapa sekvencí) vypadat následovně:
2 ['do', 'ut', 'et'] 3 ['sit', 'sed'] 5 ['Lorem', 'ipsum', 'dolor', 'amet,', 'elit,', 'magna'] 6 ['tempor', 'labore', 'dolore', 'aliqua'] 7 ['eiusmod'] 10 ['adipiscing', 'incididunt'] 11 ['consectetur']
18. Kombinace většího množství sekvencí s využitím funkce interleave
Poslední funkcí, se kterou se v dnešním článku seznámíme, je funkce s názvem interleave. Jak již název této funkce naznačuje, provádí se zde operace proložení prvků z několika vstupních sekvencí do sekvence jediné. Přitom vstupem mohou být nekonečné sekvence, jak je to ostatně ukázáno na dnešním posledním demonstračním příkladu:
from funcy import count, cycle, interleave, take values1 = count(start=1) values2 = cycle(["odd", "even"]) interleaved = interleave(values1, values2) slice = take(20, interleaved) print(slice)
V tomto demonstračním příkladu jsou proloženy prvky tvořící (nekonečnou) aritmetickou řadu s prvky získanými z nekonečné řady opakujících se hodnot „odd“ a „even“. Výsledkem je nová nekonečná řada, ze které si vybereme prvních dvacet prvků, které jsou následně vypsány na terminál:
[1, 'odd', 2, 'even', 3, 'odd', 4, 'even', 5, 'odd', 6, 'even', 7, 'odd', 8, 'even', 9, 'odd', 10, 'even']
Výsledek je tedy odlišný od použití zip namísto interleave:
from funcy import count, cycle, take values1 = count(start=1) values2 = cycle(["odd", "even"]) zipped = zip(values1, values2) slice = take(10, zipped) print(slice)
Kde výsledkem je sekvence dvojic:
[(1, 'odd'), (2, 'even'), (3, 'odd'), (4, 'even'), (5, 'odd'), (6, 'even'), (7, 'odd'), (8, 'even'), (9, 'odd'), (10, 'even')]
19. Repositář s demonstračními příklady
Všechny Pythonovské skripty, které jsme si prozatím v tomto seriálu ukázali, naleznete na adrese https://github.com/tisnik/most-popular-python-libs. Následují odkazy na jednotlivé příklady (pro jejich spuštění je nutné mít nainstalovánu některou z podporovaných verzí Pythonu 3, a pro dnešní příklady i výše zmíněnou knihovnu funcy):
20. Odkazy na Internetu
- functools — Higher-order functions and operations on callable objects
https://docs.python.org/3/library/functools.html - Functional Programming HOWTO
https://docs.python.org/3/howto/functional.html - Functional Programming in Python: When and How to Use It
https://realpython.com/python-functional-programming/ - Functional Programming With Python
https://realpython.com/learning-paths/functional-programming/ - Awesome Functional Python
https://github.com/sfermigier/awesome-functional-python - Currying
https://en.wikipedia.org/wiki/Currying - Currying in Python – A Beginner’s Introduction
https://www.askpython.com/python/examples/currying-in-python - Fundamental Concepts in Programming Languages
https://en.wikipedia.org/wiki/Fundamental_Concepts_in_Programming_Languages - When should I use function currying?
https://stackoverflow.com/questions/24881604/when-should-i-use-function-currying - Toolz
https://github.com/pytoolz/toolz/tree/master - Coconut: funkcionální jazyk s pattern matchingem kompatibilní s Pythonem
https://www.root.cz/clanky/coconut-funkcionalni-jazyk-s-pattern-matchingem-kompatibilni-s-pythonem/ - A HITCHHIKER'S GUIDE TO functools
https://ep2021.europython.eu/media/conference/slides/a-hitchhikers-guide-to-functools.pdf - Coconut aneb funkcionální nadstavba nad Pythonem (2.část)
https://www.root.cz/clanky/coconut-aneb-funkcionalni-nadstavba-nad-pythonem-2-cast/ - Knihovny pro zpracování posloupností (sekvencí) v Pythonu
https://www.root.cz/clanky/knihovny-pro-zpracovani-posloupnosti-sekvenci-v-pythonu/ - clj – repositář s knihovnou
https://github.com/bfontaine/clj - clj 0.1.0 – stránka na PyPi
https://pypi.python.org/pypi/clj/0.1.0 - Clojure aneb jazyk umožňující tvorbu bezpečných vícevláknových aplikací pro JVM (4.část – kolekce, sekvence a lazy sekvence)
https://www.root.cz/clanky/clojure-aneb-jazyk-umoznujici-tvorbu-bezpecnych-vicevlaknovych-aplikaci-pro-jvm-4-cast-kolekce-sekvence-a-lazy-sekvence/ - Clojure a bezpečné aplikace pro JVM: sekvence, lazy sekvence a paralelní programy
https://www.root.cz/clanky/clojure-a-bezpecne-aplikace-pro-jvm-sekvence-lazy-sekvence-a-paralelni-programy/ - Coconut: Simple, elegant, Pythonic functional programming
http://coconut-lang.org/ - coconut (Python package index)
https://pypi.python.org/pypi/coconut/ - Coconut Tutorial
http://coconut.readthedocs.io/en/master/HELP.html - Coconut FAQ
http://coconut.readthedocs.io/en/master/FAQ.html - Coconut Documentation
http://coconut.readthedocs.io/en/master/DOCS.html - Coconut na Redditu
https://www.reddit.com/r/Python/comments/4owzu7/coconut_functional_programming_in_python/ - Repositář na GitHubu
https://github.com/evhub/coconut - Object-Oriented Programming — The Trillion Dollar Disaster
https://betterprogramming.pub/object-oriented-programming-the-trillion-dollar-disaster-92a4b666c7c7 - Goodbye, Object Oriented Programming
https://cscalfani.medium.com/goodbye-object-oriented-programming-a59cda4c0e53 - So You Want to be a Functional Programmer (Part 1)
https://cscalfani.medium.com/so-you-want-to-be-a-functional-programmer-part-1–1f15e387e536 - So You Want to be a Functional Programmer (Part 2)
https://cscalfani.medium.com/so-you-want-to-be-a-functional-programmer-part-2–7005682cec4a - So You Want to be a Functional Programmer (Part 3)
https://cscalfani.medium.com/so-you-want-to-be-a-functional-programmer-part-3–1b0fd14eb1a7 - So You Want to be a Functional Programmer (Part 4)
https://cscalfani.medium.com/so-you-want-to-be-a-functional-programmer-part-4–18fbe3ea9e49 - So You Want to be a Functional Programmer (Part 5)
https://cscalfani.medium.com/so-you-want-to-be-a-functional-programmer-part-5-c70adc9cf56a - So You Want to be a Functional Programmer (Part 6)
https://cscalfani.medium.com/so-you-want-to-be-a-functional-programmer-part-6-db502830403 - Why Programmers Need Limits
https://cscalfani.medium.com/why-programmers-need-limits-3d96e1a0a6db - Infographic showing code complexity vs developer experience
https://twitter.com/rossipedia/status/1580639227313676288 - Python's reduce(): From Functional to Pythonic Style
https://realpython.com/python-reduce-function/ - What is the problem with reduce()?
https://stackoverflow.com/questions/181543/what-is-the-problem-with-reduce - The fate of reduce() in Python 3000
https://www.artima.com/weblogs/viewpost.jsp?thread=98196 - Reading 16: Map, Filter, Reduce
http://web.mit.edu/6.031/www/sp22/classes/16-map-filter-reduce/ - Currying
https://sw-samuraj.cz/2011/02/currying/ - Používání funkcí v F#
https://docs.microsoft.com/cs-cz/dotnet/fsharp/tutorials/using-functions - Funkce vyššího řádu
http://naucte-se.haskell.cz/funkce-vyssiho-radu - Currying (Wikipedia)
https://en.wikipedia.org/wiki/Currying - Currying (Haskell wiki)
https://wiki.haskell.org/Currying - Haskell Curry
https://en.wikipedia.org/wiki/Haskell_Curry - Moses Schönfinkel
https://en.wikipedia.org/wiki/Moses_Sch%C3%B6nfinkel - ML – funkcionální jazyk s revolučním typovým systémem
https://www.root.cz/clanky/ml-funkcionalni-jazyk-s-revolucnim-typovym-systemem/ - Funkce a typový systém programovacího jazyka ML
https://www.root.cz/clanky/funkce-a-typovy-system-programovaciho-jazyka-ml/ - Curryfikace (currying), výjimky a vlastní operátory v jazyku ML
https://www.root.cz/clanky/curryfikace-currying-vyjimky-a-vlastni-operatory-v-jazyku-ml/ - Primer on Python Decorators
https://realpython.com/primer-on-python-decorators/ - Python Decorators
https://www.programiz.com/python-programming/decorator - PythonDecorators (Python Wiki)
https://wiki.python.org/moin/PythonDecorators - Funcy na GitHubu
https://github.com/suor/funcy/ - Welcome to funcy documentation!
https://funcy.readthedocs.io/en/stable/ - Funcy cheatsheet
https://funcy.readthedocs.io/en/stable/cheatsheet.html - PyToolz API Documentation
https://toolz.readthedocs.io/en/latest/index.html - Toolz (PyToolz) na GitHubu
https://github.com/pytoolz/toolz - Fn.py: enjoy FP in Python
https://github.com/kachayev/fn.py - Funcy na PyPi
https://pypi.org/project/funcy/ - Underscore aneb další knihovna pro funkcionální programování v JavaScriptu
https://www.root.cz/clanky/underscore-aneb-dalsi-knihovna-pro-funkcionalni-programovani-v-javascriptu/ - Funkce vyššího řádu v knihovně Underscore
https://www.root.cz/clanky/funkce-vyssiho-radu-v-knihovne-underscore/ - Awesome functional Python
https://github.com/sfermigier/awesome-functional-python - lispy
https://pypi.org/project/lispy/ - clojure_py na indexu PyPi
https://pypi.python.org/pypi/clojure_py - PyClojure
https://github.com/eigenhombre/PyClojure - Hy na GitHubu
https://github.com/hylang/hy - Hy: The survival guide
https://notes.pault.ag/hy-survival-guide/ - Hy běžící na monitoru terminálu společnosti Symbolics
http://try-hy.appspot.com/ - Welcome to Hy’s documentation!
http://docs.hylang.org/en/stable/ - Hy na PyPi
https://pypi.org/project/hy/#description - Getting Hy on Python
https://lwn.net/Articles/596626/