Funkce vyššího řádu určené pro zpracování sekvencí v knihovně funcy

30. 8. 2023
Doba čtení: 40 minut

Sdílet

 Autor: Depositphotos
Knihovna funcy, s níž jsme se začali seznamovat minule, nabízí možnost zpracování sekvencí, ať již sekvencí konečných či nekonečných. Dnes se seznámíme s nejužitečnějšími funkcemi určenými pro zpracování sekvencí.

Obsah

1. Funkce vyššího řádu určené pro zpracování sekvencí v knihovně funcy

2. Sekvence a lazy sekvence v programovacích jazycích

3. Funkce vyššího řádu filter z knihovny funcy

4. Funkce vyššího řádu lfilter

5. Předání lambda výrazu do funkcí vyššího řádu filter a lfilter

6. Rozšířená „sémantika funkcí“ v knihovně funcy

7. Regulární výraz ve funkci predikátu

8. Množina ve funkci predikátu

9. Funkce vyššího řádu remove a lremove

10. Funkce vyššího řádu map v knihovně funcy

11. Funkce vyššího řádu lmap

12. Použití regulárního výrazu namísto transformační funkce v lmap

13. Získání unikátních prvků ze vstupní sekvence funkcí distinct

14. Filtrace prvků sekvence funkcí takewhile

15. Filtrace prvků sekvence funkcí dropwhile

16. Rozdělení sekvence na prvky odpovídající predikátu a na prvky, které predikátu neodpovídají

17. Kombinace funkcí vyššího řádu takewhile a dropwhile

18. Rozdělení prvků sekvence do většího množství sekvencí pomocí partition_by

19. Repositář s demonstračními příklady

20. Odkazy na Internetu

1. Funkce vyššího řádu určené pro zpracování sekvencí v knihovně funcy

V seriálu o programovacím jazyce Clojure, který na Rootu vyšel, jsme se již mnohokrát setkali s pojmem sekvence, popř. nekonečné sekvence nebo dokonce lazy (líné) sekvence. Připomeňme si, že se jedná o datovou abstrakci, která je sice velmi jednoduchá, ale o to užitečnější v praxi – ostatně velká část standardní knihovny Clojure je na sekvencích založena. Pro ty programátory, kteří programovací jazyk Clojure znají a současně používají i Python, je určena minimalisticky pojatá knihovna nazvaná clj. V této knihovně nalezneme implementaci všech základních funkcí, které jsou v Clojure určeny pro práci se sekvencemi. Tyto funkce je možné použít i pro klasické seznamy a iterátory, jak ostatně uvidíme v dalším textu (i když v poněkud jiném kontextu).

Dnes se ovšem zaměříme nikoli na výše zmíněnou knihovnu clj, ale na knihovnu, které jsme se začali věnovat minule – jedná se o knihovnu s příhodným názvem funcy. I tato knihovna programátorům poskytuje funkce pro práci se sekvencemi, přičemž názvy příslušných operací jsou mnohdy totožné s Clojure či s výše zmíněnou knihovnou clj.

2. Sekvence a lazy sekvence v programovacích jazycích

Naprostý základ pro práci se sekvencemi tvoří trojice funkcí nazvaných first, rest a rest. Funkce first vrací první prvek v sekvenci, popř. speciální hodnotu None v případě, že je sekvence prázdná (pro tyto funkce je typické, že nevyhazují výjimky). Funkce rest vrací zbylé prvky v sekvenci. Běžných sekvencí, například seznamů, mohou být tyto funkce implementovány přímočaře, ovšem v případě lazy sekvencí se prvky vrácené pomocí funkce first vyhodnocují až za běhu, například pomocí nějaké generátorové funkce. Tímto způsobem je možné pracovat i s nekonečnými sekvencemi, u nichž už z principu nelze dopředu znát celkový počet prvků atd.

Další poskytované funkce nad touto abstrakcí staví další vrstvu abstrakce, která umožňuje pracovat se sekvencemi voláním několika funkcí vyššího řádu, navíc bez nutnosti psát explicitně programové smyčky (ty se ostatně píšou resp. spouští špatně pro nekonečné sekvence). Mezi funkce z další vrstvy abstrakce patří zejména:

Operace Funkce
výběr prvků na základě kritéria filter, lfilter, remove, lremove
nová sekvence získaná aplikací nějaké funkce na všechny prvky původní sekvence map, lmap
výběr unikátních prvků ze sekvence distinct
filtrace s vyhledáním prvního „důležitého“ prvku (zarážky) takewhile
filtrace až do prvního „důležitého“ prvku takewhile
rozdělení prvků do několika sekvencí split, split_by, partition_by

Všechny tyto funkce si dnes popíšeme.

3. Funkce vyššího řádu filter z knihovny funcy

S funkcí vyššího řádu filter jsme se již v tomto miniseriálu setkali, mj. i proto, že se jedná o funkci, která je součástí standardní knihovny programovacího jazyka Python (a dokonce ji nalezneme i ve výchozím jmenném prostoru, takže ji ani nemusíme importovat). Připomeňme si, že tato funkce vybere (vyfiltruje) prvky z nějaké sekvence na základě vyhodnocení takzvaného predikátu, což je funkce, která pro každý prvek vrací pravdivostní hodnotu (resp. v Pythonu libovolnou hodnotu, která je ovšem chápána v pravdivostním kontextu).

Podívejme se na jednoduchý příklad, který již známe:

message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
words = message.split()
 
filtered = filter(lambda word: len(word) > 4, words)
print(filtered)
print(list(filtered))
 
print()
 
filtered = filter(lambda word: len(word) <= 4, words)
print(filtered)
print(list(filtered))

Výsledky budou vypadat následovně:

<filter object at 0x7f40b0bb2040>
['Lorem', 'ipsum', 'dolor', 'amet,', 'consectetur', 'adipiscing', 'elit,', 'eiusmod', 'tempor', 'incididunt', 'labore', 'dolore', 'magna', 'aliqua']
 
<filter object at 0x7f40b0b85c70>
['sit', 'sed', 'do', 'ut', 'et']
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/filter1.py.

I v knihovně funcy nalezneme funkci nazvanou filter. Tato funkce je zdánlivě totožná se standardní funkcí filter, ovšem v dalších kapitolách uvidíme, že jsou její schopnosti ve skutečnosti mnohem větší. Ale pro standardní predikáty i pro stejný vstup získáme naprosto totožné výsledky:

from funcy import filter
 
 
message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
words = message.split()
 
filtered = filter(lambda word: len(word) > 4, words)
print(filtered)
print(list(filtered))
 
print()
 
filtered = filter(lambda word: len(word) <= 4, words)
print(filtered)
print(list(filtered))

Výsledky budou vypadat naprosto stejně, jako v prvním příkladu:

<filter object at 0x7f02645f5040>
['Lorem', 'ipsum', 'dolor', 'amet,', 'consectetur', 'adipiscing', 'elit,', 'eiusmod', 'tempor', 'incididunt', 'labore', 'dolore', 'magna', 'aliqua']
 
<filter object at 0x7f02645c8c10>
['sit', 'sed', 'do', 'ut', 'et']
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/filter2.py.

4. Funkce vyššího řádu lfilter

Kromě známé funkce filter nalezneme v knihovně funcy i funkci nazvanou podobně, ovšem s prefixem „l“. Plné jméno této funkce tedy zní lfilter a onen prefix „l“ znamená, že výsledkem činnosti této funkce není generátor, ale plnohodnotný seznam (list). Ostatní vlastnosti ovšem zůstanou zachovány, o čemž se můžeme velmi snadno přesvědčit spuštěním následujícího skriptu:

from funcy import lfilter
 
 
message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
words = message.split()
 
filtered = lfilter(lambda word: len(word) > 4, words)
print(filtered)
print(list(filtered))
 
print()
 
filtered = lfilter(lambda word: len(word) <= 4, words)
print(filtered)
print(list(filtered))

Výsledkem by měl být po obou voláních seznam, takže další převod na seznam standardní funkcí list je již v tomto případě zbytečný:

['Lorem', 'ipsum', 'dolor', 'amet,', 'consectetur', 'adipiscing', 'elit,', 'eiusmod', 'tempor', 'incididunt', 'labore', 'dolore', 'magna', 'aliqua']
['Lorem', 'ipsum', 'dolor', 'amet,', 'consectetur', 'adipiscing', 'elit,', 'eiusmod', 'tempor', 'incididunt', 'labore', 'dolore', 'magna', 'aliqua']
 
['sit', 'sed', 'do', 'ut', 'et']
['sit', 'sed', 'do', 'ut', 'et']
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/filter3.py.

5. Předání lambda výrazu do funkcí vyššího řádu filter a lfilter

Asi nebude velkým překvapením, že jak do funkce filter, tak i do funkce lfilter lze předat libovolný lambda výraz, jehož výsledek je použit pro určení, zda se má právě testovaný prvek předat do výsledné sekvence (či seznamu). Jen pro naprostou úplnost:

from funcy import filter, lfilter
 
data = range(0, 11)
 
print("filter")
 
filtered = filter(lambda value : value %2 == 1, data)
print(list(filtered))
 
filtered = filter(lambda value : value %2 == 0, data)
print(list(filtered))
 
print()
print("lfilter")
 
filtered = lfilter(lambda value : value %2 == 1, data)
print(filtered)
 
filtered = lfilter(lambda value : value %2 == 0, data)
print(filtered)

Výsledky by měly vypadat následovně:

filter
[1, 3, 5, 7, 9]
[0, 2, 4, 6, 8, 10]
 
lfilter
[1, 3, 5, 7, 9]
[0, 2, 4, 6, 8, 10]
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/filter4.py.

6. Rozšířená „sémantika funkcí“ v knihovně funcy

Vážený čtenář se pravděpodobně po přečtení předchozí kapitoly ptá, proč je vůbec zdůrazněno, že funkce filter a lfilter akceptují lambda výraz (či běžnou funkci). To je přece naprosto logické a očekávatelné. Ovšem v knihovně funcy je „sémantika funkcí“ u predikátů rozšířena, což znamená, že namísto běžné funkce můžeme do filter či lfilter předat i jinou hodnotu ve funkci predikátu. Jak bude tato hodnota využita je naznačeno v tabulce:

Typ hodnoty Způsob využití jako predikátu
funkce klasický predikát volaný s hodnotou aktuálně zpracovávaného prvku
lambda výraz klasický predikát volaný s hodnotou aktuálně zpracovávaného prvku
řetězec testování prvku s využitím re_tester (tedy řetězec je chápán jako regulární výraz)
množina test, zda je zpracovávaný prvek prvkem této množiny
celé číslo volá se itemgetter(f)

7. Regulární výraz ve funkci predikátu

Podívejme se nyní, jak snadné je zadat regulární výraz ve funkci predikátu. Může se dokonce jednat o běžný řetězec, který je vyhledáván ve vstupních prvcích a pokud je nalezen, je prvek vložen do výsledné sekvence a/nebo seznamu (v závislosti na tom, zda se použije filter nebo lfilter). V posledním případě vyhledáváme ta slova, která končí na „or“, ostatní případy vyhledávají sekvenci znaků kdekoli ve slově:

from funcy import lfilter
 
 
message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
words = message.split()
 
filtered = lfilter("et", words)
print(filtered)
 
filtered = lfilter("a", words)
print(filtered)
 
filtered = lfilter("o", words)
print(filtered)
 
filtered = lfilter("or$", words)
print(filtered)

Výsledky získané po spuštění tohoto demonstračního příkladu:

['amet,', 'consectetur', 'et']
['amet,', 'adipiscing', 'labore', 'magna', 'aliqua']
['Lorem', 'dolor', 'consectetur', 'do', 'eiusmod', 'tempor', 'labore', 'dolore']
['dolor', 'tempor']
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/filter5.py.

8. Množina ve funkci predikátu

Víme již, že jako predikát lze zadat i množinu. Každý prvek, který je v této množině nalezen, se stane součástí výsledné sekvence (nebo seznamu), takže vlastní způsob použití je triviální:

from funcy import lfilter
 
 
message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
words = message.split()
 
filtered = lfilter({"sit"}, words)
print(filtered)
 
filtered = lfilter({"sit", "sed", "do"}, words)
print(filtered)
 
filtered = lfilter({"foo", "sed", "bar"}, words)
print(filtered)

Výsledky dokazují, jak vše pracuje:

['sit']
['sit', 'sed', 'do']
['sed']
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/filter6.py.

Množina je sice použita jako predikát, ovšem ve výsledné sekvenci/seznamu se samozřejmě prvky mohou opakovat (nejedná se o množinu). Zkusme si to na sekvenci slov, kde se jednotlivá slova 3× opakují:

from funcy import lfilter
 
 
message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
message *= 3
 
print(message)
 
words = message.split()
 
filtered = lfilter({"sit"}, words)
print(filtered)
 
filtered = lfilter({"sit", "sed", "do"}, words)
print(filtered)
 
filtered = lfilter({"foo", "sed", "bar"}, words)
print(filtered)

Výsledné zprávy ukazují, že ve vytvořených seznamech se prvky skutečně mohou opakovat:

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliquaLorem ipsum dolor sit amet,
consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et
dolore magna aliquaLorem ipsum dolor sit amet, consectetur adipiscing elit, sed
do eiusmod tempor incididunt ut labore et dolore magna aliqua
['sit', 'sit', 'sit']
['sit', 'sed', 'do', 'sit', 'sed', 'do', 'sit', 'sed', 'do']
['sed', 'sed', 'sed']
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/filter7.py.

9. Funkce vyššího řádu remove a lremove

Funkce filter a lfilter se používají pro vytvoření nové sekvence (nebo seznamu), která bude obsahovat jen ty prvky ze sekvence původní, které odpovídají nějakému predikátu (predikát je obecně funkce vracející pro svůj jediný vstup pravdivostní hodnotu). Funkce remove a lremove pracují přesně naopak, tj. odstraňují ze sekvence/seznamu ty prvky, které odpovídají predikátu.

Poznámka: jedná se tedy o obdobu filter/lfilter, ovšem význam predikátu je znegován.

Otestování funkce remove bude snadné. Nejprve si vyzkoušíme odstranění příliš krátkých či naopak příliš dlouhých slov:

from funcy import remove
 
 
message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
words = message.split()
 
removed = remove(lambda word: len(word) > 4, words)
print(removed)
print(list(removed))
 
print()
 
removed = remove(lambda word: len(word) <= 4, words)
print(removed)
print(list(removed))

S tímto výsledkem:

<itertools.filterfalse object at 0x7f0d7b3b9040>
['sit', 'sed', 'do', 'ut', 'et']
 
<itertools.filterfalse object at 0x7f0d7b38cbe0>
['Lorem', 'ipsum', 'dolor', 'amet,', 'consectetur', 'adipiscing', 'elit,', 'eiusmod', 'tempor', 'incididunt', 'labore', 'dolore', 'magna', 'aliqua']
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/remove1.py.

Namísto funkce remove můžeme použít i funkci lremove s odlišným typem výsledků:

from funcy import lremove
 
 
message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
words = message.split()
 
removed = lremove(lambda word: len(word) > 4, words)
print(removed)
print(list(removed))
 
print()
 
removed = lremove(lambda word: len(word) <= 4, words)
print(removed)
print(list(removed))

Výsledky:

['sit', 'sed', 'do', 'ut', 'et']
['sit', 'sed', 'do', 'ut', 'et']
 
['Lorem', 'ipsum', 'dolor', 'amet,', 'consectetur', 'adipiscing', 'elit,', 'eiusmod', 'tempor', 'incididunt', 'labore', 'dolore', 'magna', 'aliqua']
['Lorem', 'ipsum', 'dolor', 'amet,', 'consectetur', 'adipiscing', 'elit,', 'eiusmod', 'tempor', 'incididunt', 'labore', 'dolore', 'magna', 'aliqua']
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/remove2.py.

Použití lremove společně s regulárními výrazy namísto predikátů:

from funcy import lremove
 
 
message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
words = message.split()
 
removed = lremove("et", words)
print(removed)
 
removed = lremove("a", words)
print(removed)
 
removed = lremove("o", words)
print(removed)

Výsledky:

['Lorem', 'ipsum', 'dolor', 'sit', 'adipiscing', 'elit,', 'sed', 'do', 'eiusmod', 'tempor', 'incididunt', 'ut', 'labore', 'dolore', 'magna', 'aliqua']
['Lorem', 'ipsum', 'dolor', 'sit', 'consectetur', 'elit,', 'sed', 'do', 'eiusmod', 'tempor', 'incididunt', 'ut', 'et', 'dolore']
['ipsum', 'sit', 'amet,', 'adipiscing', 'elit,', 'sed', 'incididunt', 'ut', 'et', 'magna', 'aliqua']
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/remove3.py.

A konečně použití lremove společně s množinami namísto predikátu:

from funcy import lremove
 
 
message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
words = message.split()
 
removed = lremove({"sit"}, words)
print(removed)
 
removed = lremove({"sit", "sed", "do", "amet"}, words)
print(removed)
 
removed = lremove({"foo", "sed", "bar"}, words)
print(removed)

Výsledky nyní budou vypadat následovně:

['Lorem', 'ipsum', 'dolor', 'amet,', 'consectetur', 'adipiscing', 'elit,', 'sed', 'do', 'eiusmod', 'tempor', 'incididunt', 'ut', 'labore', 'et', 'dolore', 'magna', 'aliqua']
['Lorem', 'ipsum', 'dolor', 'amet,', 'consectetur', 'adipiscing', 'elit,', 'eiusmod', 'tempor', 'incididunt', 'ut', 'labore', 'et', 'dolore', 'magna', 'aliqua']
['Lorem', 'ipsum', 'dolor', 'sit', 'amet,', 'consectetur', 'adipiscing', 'elit,', 'do', 'eiusmod', 'tempor', 'incididunt', 'ut', 'labore', 'et', 'dolore', 'magna', 'aliqua']
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/remove4.py.

10. Funkce vyššího řádu map v knihovně funcy

V knihovně funcy nalezneme i klasickou funkci vyššího řádu nazvanou map. Připomeňme si, že základní variantu této funkce již velmi dobře známe, protože je součástí standardního jmenného prostoru Pythonu. Jen pro zopakování si ukažme, jak tato funkce dokáže na jednotlivé prvky vstupní sekvence aplikovat nějakou uživatelem zadanou funkci, například funkci len:

message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
words = message.split()
 
lengths = map(len, words)
 
print(lengths)
print(list(lengths))

Výsledkem bude speciální objekt, který lze ovšem v případě potřeby převést na seznam:

<map object at 0x7f2cf895d040>
[5, 5, 5, 3, 5, 11, 10, 5, 3, 2, 7, 6, 10, 2, 6, 2, 6, 5, 6]
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/map1.py.

Funkce map z knihovny funcy se bude pro stejné vstupy chovat naprosto totožným způsobem:

from funcy import map
 
message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
words = message.split()
 
lengths = map(len, words)
 
print(lengths)
print(list(lengths))

Výsledky:

<map object at 0x7f2500a2f040>
[5, 5, 5, 3, 5, 11, 10, 5, 3, 2, 7, 6, 10, 2, 6, 2, 6, 5, 6]
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/map2.py.

11. Funkce vyššího řádu lmap

Podobně jako existuje funkce filter ve dvou variantách nazvaných filter a lfilter, je tomu podobně i u funkce map, ke které existuje alternativa nazvaná lmap vracející přímo seznam a nikoli speciální objekt „map“. Tuto funkci si opět můžeme velmi snadno otestovat:

from funcy import lmap
 
message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
words = message.split()
 
lengths = lmap(len, words)
 
print(lengths)
print(list(lengths))

Výsledkem volání lmap je seznam, takže se po spuštění tohoto skriptu vypíšou dva totožné řádky:

[5, 5, 5, 3, 5, 11, 10, 5, 3, 2, 7, 6, 10, 2, 6, 2, 6, 5, 6]
[5, 5, 5, 3, 5, 11, 10, 5, 3, 2, 7, 6, 10, 2, 6, 2, 6, 5, 6]
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/map3.py.

12. Použití regulárního výrazu namísto transformační funkce v lmap

I u funkcí map a lmap lze namísto klasické transformační funkce použít regulární výraz. Interně se potom bude volat standardní funkce re_find, která vrátí nalezený řetězec, resp. přesněji řečeno řetězec odpovídající regulárnímu výrazu.

Nejprve si vše otestujme na regulárním výrazu, který pouze obsahuje nějakou sekvenci znaků a nikoli znaky se speciálním významem (hvězdičky, tečky, otazníky, závorky všeho druhu atd.):

from funcy import lmap
 
message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
words = message.split()
 
found = lmap("olo", words)
 
print(found)

Výsledkem bude následující seznam (v případě map pak sekvence), obsahující prakticky samé hodnoty None pro slova, která neobsahují sekvenci znaků „olo“ a hodnoty „olo“ pro původní slova „dolor“ a „dolore“:

[None, None, 'olo', None, None, None, None, None, None, None, None, None, None, None, None, None, 'olo', None, None]
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/map4.py.

Zajímavější situace nastane, pokud bude regulární výraz obsahovat žolíkové znaky atd.:

from funcy import lmap
 
message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
words = message.split()
 
found = lmap(".*olo.*", words)
 
print(found)

Nyní bude možné všechna slova obsahující sekvenci znaků „olo“ ponechat na výstupu, zbylá slova se nahradí za None:

[None, None, 'dolor', None, None, None, None, None, None, None, None, None, None, None, None, None, 'dolore', None, None]

Regulární výrazy ve funkcích map/lmap tedy mají poněkud méně způsobů použití, než ve funkcích filter/lfilter/remove/lremove.

Poznámka: úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/map5.py.

13. Získání unikátních prvků ze vstupní sekvence funkcí distinct

Další užitečnou dvojicí funkcí pro práci se sekvencemi, kterou nalezneme v knihovně funcy, jsou funkce určené pro získání všech unikátních prvků ze vstupní sekvence – tj. výsledkem bude nová sekvence nebo seznam, v němž nebudou duplikátní prvky. Tato dvojice funkcí se jmenuje distinct a ldistinct (tj. jedná se o jméno, které nalezneme i v mnoha funkcionálních programovacích jazycích).

Podívejme se nejdříve na funkci distinct aplikovanou na sekvenci slov, přičemž se všechna slova v této sekvenci opakují nejméně třikrát:

from funcy import distinct
 
 
message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
message *= 3
 
print(message)
 
words = message.split()
 
distilled = distinct(words)
print(distilled)
print(list(distilled))

Tento skript nejprve vypíše upravený vstup (původní zpráva je ještě dvakrát zduplikována) a dále výsledek získaný funkcí distinct:

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliquaLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliquaLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua
<generator object distinct at 0x7f76aa513510>
['Lorem', 'ipsum', 'dolor', 'sit', 'amet,', 'consectetur', 'adipiscing', 'elit,', 'sed', 'do', 'eiusmod', 'tempor', 'incididunt', 'ut', 'labore', 'et', 'dolore', 'magna', 'aliquaLorem', 'aliqua']

Povšimněte si, že ve výsledné sekvenci se skutečně žádné slovo neopakuje – všechny prvky jsou unikátní.

Poznámka: úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/distinct1.py.

Funkce ldistinct se od výše popsané funkce distinct odlišuje jen tím, že – jak jste správně uhodli – nevrací sekvenci, ale seznam s unikátními prvky:

from funcy import ldistinct
 
 
message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
message *= 3
 
print(message)
 
words = message.split()
 
distilled = ldistinct(words)
print(distilled)
print(list(distilled))

Výsledky vypsané tímto skriptem ukazují, že se skutečně vrátil přímo seznam (dvě poslední zprávy jsou totožné):

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliquaLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliquaLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua
['Lorem', 'ipsum', 'dolor', 'sit', 'amet,', 'consectetur', 'adipiscing', 'elit,', 'sed', 'do', 'eiusmod', 'tempor', 'incididunt', 'ut', 'labore', 'et', 'dolore', 'magna', 'aliquaLorem', 'aliqua']
['Lorem', 'ipsum', 'dolor', 'sit', 'amet,', 'consectetur', 'adipiscing', 'elit,', 'sed', 'do', 'eiusmod', 'tempor', 'incididunt', 'ut', 'labore', 'et', 'dolore', 'magna', 'aliquaLorem', 'aliqua']
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/distinct2.py.

14. Filtrace prvků sekvence funkcí takewhile

Ze sekvencí (a to i ze sekvencí nekonečných) je možné získat začátek či naopak zbytek sekvence s využitím funkcí nazvaných takewhile a dropwhile. Těmto funkcím je zapotřebí v prvním parametru předat takzvaný predikát určující, zda prvek splňuje nějakou podmínku (ovšem pozor – chování je odlišné od již dříve popsané funkce filter či remove). V případě prvního parametru předávaného do takewhile a dropwhile se jedná o běžnou funkci popř. o funkci anonymní, která by měla akceptovat jeden parametr (hodnotu prvku ze sekvence) a vracet by měla pravdivostní hodnotu True či False popř. None atd., který má v kontextu pravdivostních hodnot stejný význam jako False.

Podívejme se, jak lze získat ty prvky ze začátku sekvence, které jsou menší než 10 (výsledkem může být i prázdná sekvence):

from funcy import takewhile
 
values = range(1000)
 
selected = takewhile(lambda x:x < 10, values)
 
print(selected)
print(list(selected))

Výsledek:

<itertools.takewhile object at 0x7f4593b7bd80>
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/ta­ke_while1.py.

Ve druhém demonstračním příkladu začneme procházet sekvencí slov s tím, že se zastavíme na prvním slovu, které nebude delší než dva znaky:

from funcy import takewhile
 
message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
words = message.split()
 
filtered = takewhile(lambda x:len(x) > 2, words)
 
print(filtered)
print(list(filtered))

Výsledek:

<itertools.takewhile object at 0x7f4250789dc0>
['Lorem', 'ipsum', 'dolor', 'sit', 'amet,', 'consectetur', 'adipiscing', 'elit,', 'sed']
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/ta­ke_while2.py.

15. Filtrace prvků sekvence funkcí dropwhile

Vyzkoušejme si nyní funkci vyššího řádu dropwhile. Přeskočíme všechny prvky na začátku sekvence, které jsou ostře menší než 990. Vrátí se zbytek sekvence, v tomto konkrétním případě hodnoty od 990 do 999 (včetně):

from funcy import dropwhile
 
values = range(1000)
 
selected = dropwhile(lambda x:x < 990, values)
 
print(selected)
print(list(selected))

Výsledek:

<itertools.dropwhile object at 0x7f9a46e10e00>
[990, 991, 992, 993, 994, 995, 996, 997, 998, 999]
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/drop_whi­le1.py.

V dalším skriptu se přeskočí všechna slova na začátku sekvence, která jsou delší než dva znaky. Jakmile se nalezne kratší slovo, vrátí se celý zbytek sekvence:

from funcy import dropwhile
 
message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
words = message.split()
 
filtered = dropwhile(lambda x:len(x) > 2, words)
 
print(filtered)
print(list(filtered))

Výsledek:

<itertools.dropwhile object at 0x7f6604fbad00>
['do', 'eiusmod', 'tempor', 'incididunt', 'ut', 'labore', 'et', 'dolore', 'magna', 'aliqua']
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/drop_whi­le2.py.

16. Rozdělení sekvence na prvky odpovídající predikátu a na prvky, které predikátu neodpovídají

Potenciálně velmi užitečná je funkce nazvaná split. Jedná se o kombinaci funkcí filter a remove – split vrátí dvě hodnoty, přičemž první hodnotou bude sekvence s prvky odpovídajícími predikátu a ve druhé hodnotě budou všechny prvky, které predikátu neodpovídají:

from funcy import split
 
values = range(50)
 
selected, unselected = split(lambda x:x < 25, values)
 
print(list(selected))
print(list(unselected))

Pokud tento skript spustíme, vrátí se dvě sekvence s tímto obsahem:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]
[25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49]
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/split1.py.

Existuje samozřejmě i alternativní funkce nazvaná lsplit, která vrací dvojici seznamů:

from funcy import lsplit
 
values = range(50)
 
selected, unselected = lsplit(lambda x:x < 25, values)
 
print(selected)
print(unselected)

Výsledek získaný po spuštění tohoto skriptu bude stejný, jako v předchozím případě, ovšem chybí zde konstruktor seznamu list:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]
[25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49]
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/split2.py.

Podobně si můžeme nechat rozdělit sekvenci slov na dlouhá a krátká slova:

from funcy import split
 
message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
words = message.split()
 
selected, unselected = split(lambda x:len(x) > 5, words)
 
print(list(selected))
print(list(unselected))

S výsledkem:

['consectetur', 'adipiscing', 'eiusmod', 'tempor', 'incididunt', 'labore', 'dolore', 'aliqua']
['Lorem', 'ipsum', 'dolor', 'sit', 'amet,', 'elit,', 'sed', 'do', 'ut', 'et', 'magna']
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/split3.py.

A pro úplnost alternativní řešení založené na funkci vyššího řádu lsplit:

from funcy import lsplit
 
message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
words = message.split()
 
selected, unselected = lsplit(lambda x:len(x) > 5, words)
 
print(selected)
print(unselected)

Výsledná dvojice seznamů:

['consectetur', 'adipiscing', 'eiusmod', 'tempor', 'incididunt', 'labore', 'dolore', 'aliqua']
['Lorem', 'ipsum', 'dolor', 'sit', 'amet,', 'elit,', 'sed', 'do', 'ut', 'et', 'magna']
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/split4.py.

17. Kombinace funkcí vyššího řádu takewhile a dropwhile

V předchozí kapitole jsme si ukázali, jak snadno se s využitím funkce split daly zkombinovat algoritmy realizované ve funkcích filter a remove. Knihovna funcy jde ovšem ještě dále a nabízí uživatelům možnost kombinace funkcí takewhile a dropwhile, které vlastně mají taktéž „komplementární“ význam. Ona kombinace je realizována ve funkci nazvané split_by, které se předává predikát a vstupní sekvence. Funkce split_by vrátí dvojici sekvencí, přičemž v první výstupní sekvenci budou uloženy prvky získané ze začátku vstupní sekvence, které odpovídají predikátu, a ve druhé výstupní sekvenci zbytek vstupní sekvence (tj. od toho prvku, který jako první neodpovídá predikátu).

Podívejme se, jak to bude vypadat pro vstupní sekvenci s hodnotami 0 až 99 a predikát „x < 10“:

from funcy import split_by
 
values = range(100)
 
selected, rest = split_by(lambda x:x < 10, values)
 
print(list(selected))
print(list(rest))

Výsledkem budou dvě sekvence; rozdělení začalo (podle očekávání) na prvku s hodnotou 10, který již predikátu neodpovídá:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/split_by1.py.

Podobným způsobem můžeme zpracovat sekvenci slov takovým způsobem, že nalezneme první slovo, které je kratší než dva znaky. Prvky před tímto slovem budou vráceny v první výstupní sekvenci, zbylé prvky pak v sekvenci druhé:

from funcy import split_by
 
message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
words = message.split()
 
filtered, rest = split_by(lambda x:len(x) > 2, words)
 
print(list(filtered))
print(list(rest))

Příslušné výstupní sekvence budou vypadat takto:

['Lorem', 'ipsum', 'dolor', 'sit', 'amet,', 'consectetur', 'adipiscing', 'elit,', 'sed']
['do', 'eiusmod', 'tempor', 'incididunt', 'ut', 'labore', 'et', 'dolore', 'magna', 'aliqua']
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/split_by2.py.

18. Rozdělení prvků sekvence do většího množství sekvencí pomocí partition_by

Poslední funkcí, s níž se v dnešním článku seznámíme, je funkce nazvaná partition_by. Tato funkce rozdělí vstupní sekvenci do (obecně libovolného) množství výstupních sekvencí na základě výsledku získaného výpočtem realizovaným v předané funkci. Pokud tato funkce vrací stejný výsledek (libovolného typu či hodnoty), budou prvky ukládány do stejné výstupní sekvence. Jakmile se výsledek této funkce změní, je vytvořena nová výstupní sekvence a prvky začnou být ukládány do ní.

Poznámka: pozor je zapotřebí si dát na to, že nedojde k seskupení těch prvků, pro něž předaná funkce vrací stejné hodnoty! Například takto není možné rozdělit slova podle jejich délky – museli bychom slova nejdříve seřadit podle délky a teprve poté zavolat partition_by.

Podívejme se nyní na jednoduchý příklad použití této funkce pro rozdělení sekvence celočíselných hodnot 0 až 19 do skupin po pěti prvcích. Povšimněte si, že počítanou hodnotou je x//5, tedy celočíselný podíl hodnoty prvku pěti, což u monotonně rostoucí sekvence bude plně funkční:

bitcoin_skoleni

from funcy import partition_by
 
values = range(20)
 
sequences = partition_by(lambda x : x // 5, values)
 
for sequence in sequences:
    print(list(sequence))

Výsledkem bude čtveřice sekvencí resp. přesněji řečeno sekvence se čtyřmi prvky typu sekvence:

[0, 1, 2, 3, 4]
[5, 6, 7, 8, 9]
[10, 11, 12, 13, 14]
[15, 16, 17, 18, 19]
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/par­tition_by.py.

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):

# Příklad Stručný popis Adresa
1 binary_operator.py ukázka funkce vyššího řádu, která jako parametr akceptuje jinou funkci https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/binary_operator.py
2 get_operator1.py ukázka funkce vyššího řádu, která vrací jinou funkci https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/get_operator1.py
3 get_operator2.py ukázka funkce vyššího řádu, která vrací jinou funkci https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/get_operator2.py
4 standard_operators.py použití standardních operátorů přepsaných do formy funkce https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/standard_operators.py
       
5 binary_operator_types.py varianta příkladu binary_operator.py s plnými typovými deklaracemi https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/binary_operator_types.py
6 get_operator_types.py varianta příkladu get_operator2.py s plnými typovými deklaracemi https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/get_operator_types.py
       
7 map1.py příklad použití funkce map: výpočet délky všech slov v textu https://github.com/tisnik/most-popular-python-libs/blob/master/functools/map1.py
8 map2.py příklad použití funkce map: výpočet absolutní hodnoty všech členů posloupnosti https://github.com/tisnik/most-popular-python-libs/blob/master/functools/map2.py
9 map3.py příklad použití funkce map: aplikace vlastní pojmenované funkce https://github.com/tisnik/most-popular-python-libs/blob/master/functools/map3.py
10 map4.py příklad použití funkce map: aplikace vlastního lambda výrazu https://github.com/tisnik/most-popular-python-libs/blob/master/functools/map4.py
       
11 map_list_comprehension1.py přepis skriptu map1.py tak, aby se použila generátorová notace https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/map_list_comprehension.py
12 map_list_comprehension2.py přepis skriptu map2.py tak, aby se použila generátorová notace https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/map_list_comprehension.py
13 map_list_comprehension3.py přepis skriptu map3.py tak, aby se použila generátorová notace https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/map_list_comprehension.py
14 map_list_comprehension4.py přepis skriptu map4.py tak, aby se použila generátorová notace https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/map_list_comprehension.py
       
15 filter1.py filtrace dat na základě délky řetězce https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/filter1.py
16 filter2.py filtrace numerických dat podle toho, zda se jedná o sudá či lichá čísla https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/filter2.py
17 filter3.py přepis předchozího příkladu s využitím lambda výrazu https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/filter3.py
       
18 filter_list_comprehension1.py přepis skriptu filter_list_comprehension1.py tak, aby se použila generátorová notace https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/filter_list_comprehensi­on1.py
19 filter_list_comprehension2.py přepis skriptu filter_list_comprehension2.py tak, aby se použila generátorová notace https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/filter_list_comprehensi­on2.py
20 filter_list_comprehension3.py přepis skriptu filter_list_comprehension3.py tak, aby se použila generátorová notace https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/filter_list_comprehensi­on3.py
       
21 reduce1.py výpočet faktoriálu s využitím funkce vyššího řádu reduce https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/reduce1.py
22 reduce2.py přepis předchozího příkladu s využitím lambda výrazu https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/reduce2.py
23 reduce3.py tisk tabulky faktoriálů https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/reduce3.py
24 reduce4.py přepis předchozího příkladu s využitím lambda výrazu https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/reduce4.py
25 reduce5.py přepis předchozího příkladu s využitím generátorové notace https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/reduce5.py
       
26 return_function.py funkce jako návratová hodnota jiné funkce https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/return_function.py
27 closure_adder1.py příklad použití uzávěru – konstrukce funkce typu adder https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/closure_adder1.py
28 counter_closure1.py nekorektní implementace čítače s využitím uzávěrů https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/counter_closure1.py
29 counter_closure2.py přístup k nelokálnímu symbolu (Python 2.x i Python 3.x) https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/counter_closure2.py
30 counter_closure3.py přístup k nelokálnímu symbolu (pouze Python 3.x) https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/counter_closure3.py
       
31 access_nonlocal_symbol.py přístup k nelokálnímu symbolu v uzávěru https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/access_nonlocal_symbol.py
32 functions_and_closures.py funkce a uzávěry (umělý příklad) https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/functions_and_closures.py
       
33 partial1.py funkce doubler odvozená (redukcí) z univerzálnější funkce mul https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial1.py
34 partial2.py transformace funkce se třemi parametry s využitím partial (nekorektní řešení) https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial2.py
35 partial3.py transformace funkce se třemi parametry s využitím partial (korektní řešení) https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial3.py
36 partial4.py transformace funkce s dosazením většího množství parametrů s využitím partial https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial4.py
37 partial5.py několikanásobná transformace původní funkce na několik nových funkcí https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial5.py
38 partial6.py postupná transformace již ztransformovaných funkcí https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial6.py
39 partial7.py typ originální funkce i funkcí získaných s využitím transformace pomocí partial https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial7.py
40 partial8.py jméno funkce, poziční argumenty funkce a pojmenované argumenty funkce https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial8.py
41 partial9.py transformace reduce a pojmenované argumenty původní funkce https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial9.py
42 partial_A.py získání informací o redukované funkci s pojmenovanými argumenty https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial_A.py
       
43 partial_method1.py třída s metodou s parametry https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial_method1.py
44 partial_method2.py třída s metodou s parametry – vliv volání setteru na stav objektu https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial_method2.py
45 partial_method3.py metody enable a disable vzniklé transformací set_enabled https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial_method3.py
46 partial_method4.py další příklad použití funkce partialmethod – doplnění většího množství parametrů při transformaci https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial_method4.py
       
47 lru_cache1.py klasický výpočet Fibonacciho posloupnosti rekurzivní funkcí https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/lru_cache1.py
48 lru_cache2.py LRU cache pro výsledky Fibonacciho posloupnosti pro nejčastěji použité vstupy https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/lru_cache2.py
49 lru_cache3.py přečtení informací o využití LRU cache https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/lru_cache3.py
50 lru_cache4.py programové vymazání LRU cache https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/lru_cache4.py
       
51 cached_property1.py použití standardního dekorátoru @property https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/cached_property1.py
52 cached_property2.py použití dekorátoru @cached_property https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/cached_property2.py
53 cached_property3.py úprava předchozího příkladu tak, aby se využila LRU cache https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/cached_property3.py
       
54 total_ordering.py příklad implementace relačních operátorů založených na dekorátoru @total_ordering https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/total_ordering.py
       
55 decorators2.py příklad použití jednoho dekorátoru aplikovaného na funkci https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/decorators2.py
56 decorators3.py příklad použití dvou dekorátorů aplikovaných na funkci https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/decorators3.py
57 measure_time.py praktické použití dekorátoru – měření doby trvání funkce označené dekorátorem https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/measure_time.py
       
58 decorators4.py atributy transformované funkce vytvořené s využitím dekorátoru https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/decorators4.py
59 decorators5.py využití dekorátoru @wraps pro automatickou úpravu atributů „obalované“ funkce https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/decorators5.py
60 decorators6.py dekorátor @wraps a několikanásobná aplikace dekorátorů na „obalovanou“ funkci https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/decorators6.py
       
61 decorators1.py zkrácená deklarace dekorátoru s využitím dekorátoru @decorator https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/de­corators1.py
62 decorators2.py několikanásobná aplikace dekorátorů, dekorátor je vytvořen přes @decorator https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/de­corators2.py
63 measure_time.py měření doby trvání funkce označené dekorátorem, dekorátor je vytvořen přes @decorator https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/measure_time.py
       
64 curry1.py curryfikace funkce se dvěma parametry https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/curry1.py
65 curry2.py curryfikace funkce se třemi parametry https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/curry2.py
66 rcurry1.py curryfikace funkce div funkcí curry https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/rcurry1.py
67 rcurry2.py curryfikace funkce div funkcí rcurry https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/rcurry2.py
68 rcurry3.py curryfikace funkce n_pow funkcí rcurry https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/rcurry3.py
       
69 autocurry.py curryfikace funkce n_pow funkcí autocurry (s odlišným výsledkem) https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/autocurry.py
       
70 compose1.py kompozice funkcí s využitím funkce vyššího řádu compose https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/compose1.py
71 compose2.py kompozice funkcí s využitím funkce vyššího řádu compose https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/compose2.py
72 compose3.py kompozice funkcí s využitím funkce vyššího řádu compose https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/compose3.py
73 rcompose1.py kompozice funkcí s využitím funkce vyššího řádu rcompose https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/rcompose1.py
74 rcompose2.py kompozice funkcí s využitím funkce vyššího řádu rcompose https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/rcompose2.py
75 rcompose3.py kompozice funkcí s využitím funkce vyššího řádu rcompose https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/rcompose3.py
       
76 filter1.py použití standardní funkce filter (opakování) https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/filter1.py
77 filter2.py použití funkce filter z knihovny funcy https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/filter2.py
78 filter3.py funkce vyššího řádu lfilter https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/filter3.py
79 filter4.py předání lambda výrazu do funkcí vyššího řádu filter a lfilter https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/filter4.py
80 filter5.py regulární výraz ve funkci predikátu https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/filter5.py
81 filter6.py množina ve funkci predikátu https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/filter6.py
82 filter7.py množina ve funkci predikátu https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/filter7.py
       
83 remove1.py použití funkce vyššího řádu remove https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/remove1.py
84 remove2.py použití funkce vyššího řádu lremove https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/remove2.py
85 remove3.py kombinace regulárního výrazu a funkce vyššího řádku lremove https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/remove3.py
86 remove4.py kombinace množin a funkce vyššího řádku lremove https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/remove4.py
       
87 map1.py použití standardní funkce map (opakování) https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/map1.py
88 map2.py použití funkce map z knihovny funcy https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/map2.py
89 map3.py funkce vyššího řádu lmap https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/map3.py
90 map4.py použití regulárního výrazu namísto transformační funkce v lmap https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/map4.py
91 map5.py použití regulárního výrazu namísto transformační funkce v lmap https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/map5.py
       
92 distinct1.py získání unikátních prvků ze vstupní sekvence funkcí distinct https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/distinct1.py
93 distinct2.py získání unikátních prvků ze vstupní sekvence funkcí distinct https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/distinct2.py
       
94 take_while1.py filtrace prvků sekvence funkcí takewhile https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/ta­ke_while1.py
95 take_while2.py filtrace prvků sekvence funkcí takewhile https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/ta­ke_while2.py
96 drop_while1.py filtrace prvků sekvence funkcí dropwhile https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/drop_whi­le1.py
97 drop_while2.py filtrace prvků sekvence funkcí dropwhile https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/drop_whi­le2.py
       
98 split1.py rozdělení sekvence na prvky odpovídající predikátu a na prvky, které predikátu neodpovídají https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/split1.py
99 split2.py rozdělení sekvence na prvky odpovídající predikátu a na prvky, které predikátu neodpovídají https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/split2.py
100 split3.py rozdělení sekvence na prvky odpovídající predikátu a na prvky, které predikátu neodpovídají https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/split3.py
101 split4.py rozdělení sekvence na prvky odpovídající predikátu a na prvky, které predikátu neodpovídají https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/split4.py
       
102 split_by1.py kombinace funkcí vyššího řádu takewhile a dropwhile https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/split_by1.py
103 split_by2.py kombinace funkcí vyššího řádu takewhile a dropwhile https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/split_by2.py
       
104 partition_by.py rozdělení sekvence na větší množství sekvencí funkcí partition_by https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/partition_by.py

20. Odkazy na Internetu

  1. functools — Higher-order functions and operations on callable objects
    https://docs.python.org/3/li­brary/functools.html
  2. Functional Programming HOWTO
    https://docs.python.org/3/how­to/functional.html
  3. Functional Programming in Python: When and How to Use It
    https://realpython.com/python-functional-programming/
  4. Functional Programming With Python
    https://realpython.com/learning-paths/functional-programming/
  5. Awesome Functional Python
    https://github.com/sfermigier/awesome-functional-python
  6. Currying
    https://en.wikipedia.org/wi­ki/Currying
  7. Currying in Python – A Beginner’s Introduction
    https://www.askpython.com/pyt­hon/examples/currying-in-python
  8. Fundamental Concepts in Programming Languages
    https://en.wikipedia.org/wi­ki/Fundamental_Concepts_in_Pro­gramming_Languages
  9. When should I use function currying?
    https://stackoverflow.com/qu­estions/24881604/when-should-i-use-function-currying
  10. Toolz
    https://github.com/pytool­z/toolz/tree/master
  11. Coconut: funkcionální jazyk s pattern matchingem kompatibilní s Pythonem
    https://www.root.cz/clanky/coconut-funkcionalni-jazyk-s-pattern-matchingem-kompatibilni-s-pythonem/
  12. A HITCHHIKER'S GUIDE TO functools
    https://ep2021.europython­.eu/media/conference/slides/a-hitchhikers-guide-to-functools.pdf
  13. Coconut aneb funkcionální nadstavba nad Pythonem (2.část)
    https://www.root.cz/clanky/coconut-aneb-funkcionalni-nadstavba-nad-pythonem-2-cast/
  14. Knihovny pro zpracování posloupností (sekvencí) v Pythonu
    https://www.root.cz/clanky/knihovny-pro-zpracovani-posloupnosti-sekvenci-v-pythonu/
  15. clj – repositář s knihovnou
    https://github.com/bfontaine/clj
  16. clj 0.1.0 – stránka na PyPi
    https://pypi.python.org/py­pi/clj/0.1.0
  17. 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/
  18. 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/
  19. Coconut: Simple, elegant, Pythonic functional programming
    http://coconut-lang.org/
  20. coconut (Python package index)
    https://pypi.python.org/pypi/coconut/
  21. Coconut Tutorial
    http://coconut.readthedoc­s.io/en/master/HELP.html
  22. Coconut FAQ
    http://coconut.readthedoc­s.io/en/master/FAQ.html
  23. Coconut Documentation
    http://coconut.readthedoc­s.io/en/master/DOCS.html
  24. Coconut na Redditu
    https://www.reddit.com/r/Pyt­hon/comments/4owzu7/coconut_fun­ctional_programming_in_pyt­hon/
  25. Repositář na GitHubu
    https://github.com/evhub/coconut
  26. Object-Oriented Programming — The Trillion Dollar Disaster
    https://betterprogramming.pub/object-oriented-programming-the-trillion-dollar-disaster-92a4b666c7c7
  27. Goodbye, Object Oriented Programming
    https://cscalfani.medium.com/goodbye-object-oriented-programming-a59cda4c0e53
  28. 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
  29. 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
  30. 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
  31. 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
  32. 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
  33. 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
  34. Why Programmers Need Limits
    https://cscalfani.medium.com/why-programmers-need-limits-3d96e1a0a6db
  35. Infographic showing code complexity vs developer experience
    https://twitter.com/rossi­pedia/status/1580639227313676288
  36. Python's reduce(): From Functional to Pythonic Style
    https://realpython.com/python-reduce-function/
  37. What is the problem with reduce()?
    https://stackoverflow.com/qu­estions/181543/what-is-the-problem-with-reduce
  38. The fate of reduce() in Python 3000
    https://www.artima.com/we­blogs/viewpost.jsp?thread=98196
  39. Reading 16: Map, Filter, Reduce
    http://web.mit.edu/6.031/www/sp22/clas­ses/16-map-filter-reduce/
  40. Currying
    https://sw-samuraj.cz/2011/02/currying/
  41. Používání funkcí v F#
    https://docs.microsoft.com/cs-cz/dotnet/fsharp/tutorials/using-functions
  42. Funkce vyššího řádu
    http://naucte-se.haskell.cz/funkce-vyssiho-radu
  43. Currying (Wikipedia)
    https://en.wikipedia.org/wi­ki/Currying
  44. Currying (Haskell wiki)
    https://wiki.haskell.org/Currying
  45. Haskell Curry
    https://en.wikipedia.org/wi­ki/Haskell_Curry
  46. Moses Schönfinkel
    https://en.wikipedia.org/wi­ki/Moses_Sch%C3%B6nfinkel
  47. ML – funkcionální jazyk s revolučním typovým systémem
    https://www.root.cz/clanky/ml-funkcionalni-jazyk-s-revolucnim-typovym-systemem/
  48. Funkce a typový systém programovacího jazyka ML
    https://www.root.cz/clanky/funkce-a-typovy-system-programovaciho-jazyka-ml/
  49. 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/
  50. Primer on Python Decorators
    https://realpython.com/primer-on-python-decorators/
  51. Python Decorators
    https://www.programiz.com/python-programming/decorator
  52. PythonDecorators (Python Wiki)
    https://wiki.python.org/mo­in/PythonDecorators
  53. Funcy na GitHubu
    https://github.com/suor/funcy/
  54. Welcome to funcy documentation!
    https://funcy.readthedocs­.io/en/stable/
  55. Funcy cheatsheet
    https://funcy.readthedocs­.io/en/stable/cheatsheet.html
  56. PyToolz API Documentation
    https://toolz.readthedocs­.io/en/latest/index.html
  57. Toolz (PyToolz) na GitHubu
    https://github.com/pytoolz/toolz
  58. Fn.py: enjoy FP in Python
    https://github.com/kachayev/fn.py
  59. Funcy na PyPi
    https://pypi.org/project/funcy/
  60. 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/
  61. Funkce vyššího řádu v knihovně Underscore
    https://www.root.cz/clanky/funkce-vyssiho-radu-v-knihovne-underscore/
  62. Awesome functional Python
    https://github.com/sfermigier/awesome-functional-python
  63. lispy
    https://pypi.org/project/lispy/
  64. clojure_py na indexu PyPi
    https://pypi.python.org/py­pi/clojure_py
  65. PyClojure
    https://github.com/eigenhom­bre/PyClojure
  66. Hy na GitHubu
    https://github.com/hylang/hy
  67. Hy: The survival guide
    https://notes.pault.ag/hy-survival-guide/
  68. Hy běžící na monitoru terminálu společnosti Symbolics
    http://try-hy.appspot.com/
  69. Welcome to Hy’s documentation!
    http://docs.hylang.org/en/stable/
  70. Hy na PyPi
    https://pypi.org/project/hy/#des­cription
  71. Getting Hy on Python
    https://lwn.net/Articles/596626/

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.