Funkcionální programování v Pythonu s využitím knihovny Toolz

15. 2. 2024
Doba čtení: 41 minut

Sdílet

 Autor: Depositphotos
Ve stručnosti se seznámíme s populární knihovnou nazvanou toolz (ano, se „z“ na konci). Dnes se zaměříme zejména na její balíček nazvaný Itertoolz určený pro práci s konečnými i nekonečnými sekvencemi.

Obsah

1. Funkcionální programování v Pythonu s využitím knihovny Toolz

2. Instalace knihovny toolz

3. Podbalíček itertoolz

4. Nekonečné sekvence a líné vyhodnocování

5. Základní operace se sekvencemi

6. Nekonečná sekvence s hodnotami vytvářenými s využitím uživatelské funkce

7. Vygenerování Fibonacciho posloupnosti s využitím iterate

8. Kombinace většího množství sekvencí s využitím funkce interleave

9. Funkce interleave a nekonečné sekvence

10. Rozdělení prvků sekvence do skupin s využití funkce groupby

11. Groupby a nekonečné sekvence

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

13. Rozdělení nekonečné sekvence

14. Proložení prvků sekvence další hodnotou

15. Klasická funkce reduce i její paralelní varianta

16. Postupná redukce vstupu s akumulací mezivýsledků

17. Výpočet rozdílu mezi sekvencemi

18. Rozdíly mezi větším množstvím sekvencí

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

20. Odkazy na Internetu

1. Funkcionální programování v Pythonu s využitím knihovny Toolz

V sérii článků o funkcionálním programování realizovaném v Pythonu jsme si popsali většinu vlastností standardní knihovny functools, která do Pythonu přináší některé prvky funkcionálního programování. Ovšem další funkcionální vlastnosti tato knihovna z různých důvodů nepokrývá či pokrývá jen částečně. Jedná se jak o podporu kompozice funkcí, popř. curryingu (i když partial je částečným (sic) řešením), tak i například o podporu pro neměnitelné datové typy, funkcí pro zpracování sekvencí, podporu typů Option či Result (tak jsou pojmenované v Rustu) atd. Z tohoto důvodu vznikla celá řada více či méně obsáhlých balíčků, z nichž mnohé jsou vyjmenovány (a podle oblíbenosti seřazeny) na stránce Awesome functional Python. Již jsme se ostatně s jednou z těchto knihoven seznámili. Připomeňme si, že se jednalo o knihovnu nazvanou funcy.

V osmé, tedy dnešní části již však knihovnu funcy opustíme. Ve stručnosti si popíšeme knihovnu nazvanou toolz, jejíž zdrojové kódy lze nalézt na GitHubu na adrese https://github.com/pytoolz/toolz. Tato knihovna je v komunitě vývojářů v Pythonu poměrně populární a mezi její přednosti patří minimální závislosti, malá velikost a logické rozdělení nabízených funkcí do několika podbalíčků. Oproti již popsané knihovně funcy sice (podle všech předpokladů) nalezneme několik rozdílů, ovšem základní koncepty a techniky funkcionálního programování jsou vývojářům pochopitelně stále k dispozici.

2. Instalace knihovny toolz

Instalace knihovny toolz se nijak neliší od instalace jakéhokoli jiného běžného balíčku pro Python. Pro instalaci můžeme použít například dnes již prakticky standardní nástroj pip, popř. pip3. Povšimněte si, že knihovna toolz nemá žádné další závislosti a navíc je na dnešní poměry velmi malá – její velikost při stahování dosahuje jen 56 kB a po rozbalení cca 290 kB:

$ pip install --user toolz
 
Collecting toolz
  Downloading toolz-0.12.1-py3-none-any.whl.metadata (5.1 kB)
Downloading toolz-0.12.1-py3-none-any.whl (56 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 56.1/56.1 kB 921.9 kB/s eta 0:00:00
Installing collected packages: toolz
Successfully installed toolz-0.12.1

Po instalaci si přímo v interpretru Pythonu (REPL) ověříme, jestli je balíček toolz dostupný:

import(toolz)
help(toolz)

Po vykonání těchto dvou příkazů by se měla zobrazit nápověda ke knihovně toolz:

Help on package toolz:
 
NAME
    toolz
 
PACKAGE CONTENTS
    _signatures
    _version
    compatibility
    curried (package)
    dicttoolz
    functoolz
    itertoolz
    recipes
    sandbox (package)
    utils
 
FUNCTIONS
    reduce(...)
        reduce(function, sequence[, initial]) -> value
 
        Apply a function of two arguments cumulatively to the items of a sequence,
        from left to right, so as to reduce the sequence to a single value.
        For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
        ((((1+2)+3)+4)+5).  If initial is present, it is placed before the items
        of the sequence in the calculation, and serves as a default when the
        sequence is empty.
 
    sorted(iterable, /, *, key=None, reverse=False)
        Return a new list containing all items from the iterable in ascending order.
         
        A custom key function can be supplied to customize the sort order, and the
        reverse flag can be set to request the result in descending order.
 
VERSION
    0.12.1
 
FILE
    /home/ptisnovs/.local/lib/python3.12/site-packages/toolz/__init__.py
Poznámka: povšimněte si, že se vlastně vypsala pouze dvojice funkcí. Je tomu tak z toho důvodu, že další funkce jsou „schovány“ v dalších podbalíčcích a nejsou tedy umístěny do jediného společného jmenného prostoru.

3. Podbalíček itertoolz

Prvním podbalíčkem z knihovny toolz, s nímž se v dnešním článku seznámíme, je podbalíček nazvaný přímočaře itertoolz. Nalezneme zde funkce pracující se sekvencemi a kolekcemi. Těchto funkcí je několik desítek a ty nejdůležitější z nich si popíšeme v navazujícím textu:

accumulate getter merge_sorted reduceby
collections groupby no_default remove
concat heapq no_pad rest
concatv interleave nth second
cons interpose operator sliding_window
count isdistinct partial tail
diff isiterable partition take
drop iterate partition_all take_nth
filterfalse itertools peek topk
first join peekn unique
frequencies last pluck zip_longest
get mapcat random_sample  

4. Nekonečné sekvence a líné vyhodnocování

Knihovna Toolz dokáže pracovat s konečnými sekvencemi a sekvencemi nekonečnými. Pro první typ sekvencí se někdy používá označení seznam (list), pro druhý pak proud (stream) – to je však v Pythonu poněkud matoucí. Koncept nekonečných sekvencí sice není v oblasti programovacích jazyků žádnou žhavou novinkou, ovšem do praktické podoby byl dopracován až relativně pozdě. Velmi dobrým příkladem programovacího jazyka, jenž je na tomto konceptu do značné míry postaven, je jazyk Clojure, jímž se postupně inspirují další programovací jazyky.

V knihovně Toolz a speciálně v podbalíčku Itertoolz je definováno poměrně velké množství funkcí, které dokážou pracovat se sekvencemi, ať již se jedná o běžné sekvence (jejichž prvky jsou přímo uloženy v operační paměti), nebo takzvané líné sekvence (lazy sekvence), které nové prvky vytváří či zjišťují až při konkrétním přístupu na tyto prvky. Díky tomu, že všechny standardní kolekce (seznamy, n-tice, …) jsou současně i sekvencemi, lze tyto funkce aplikovat i na kolekce, ovšem ve skutečnosti jsou sekvencemi i další typy objektů, zejména pak I/O proudy.

V dalších kapitolách tento koncept uvidíme. Například si necháme proložit prvky konečné a nekonečné sekvence a z výsledku (ten není ihned počítán – Toolz je „líná knihovna“) si necháme vypsat pouze některé vybrané prvky.

5. Základní operace se sekvencemi

Mezi šest základních operací se sekvencemi (a může se jednat o libovolné sekvence, nikoli tedy pouze například seznamy) patří tyto operace (funkce):

Operace Stručný popis
first vrátí první prvek ze sekvence
last vrátí poslední prvek ze sekvence (pokud je konečná)
take vrátí prvních n prvků ze sekvence
drop vrátí sekvenci bez prvních n prvků
nth vrátí n-tý prvek ze sekvence
get vrátí n-tý prvek ze sekvence, výběr ze slovníku podle klíče, dokáže pracovat s neznámými hodnotami

Pojďme si nyní ve stručnosti tyto operace ukázat. Příklady jsou tak jednoduché, že si namísto jejich popisu pouze uvedeme vypočtené výsledky.

První prvek sekvence:

from toolz.itertoolz import first
 
values = [chr(i) for i in range(ord('A'), ord('Z')+1)]
 
print(values)
print(first(values))

Výsledek:

['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
A

Poslední prvek sekvence:

from toolz.itertoolz import last
 
values = [chr(i) for i in range(ord('A'), ord('Z')+1)]
 
print(values)
print(last(values))

Výsledek:

['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
Z

Prvních n prvků sekvence:

from toolz.itertoolz import take
 
values = [chr(i) for i in range(ord('A'), ord('Z')+1)]
 
print(values)
print(list(take(10, values)))

Výsledek:

['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J']

Sekvence bez prvních n prvků:

from toolz.itertoolz import drop
 
values = [chr(i) for i in range(ord('A'), ord('Z')+1)]
 
print(values)
print(list(drop(10, values)))

Výsledek:

['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
['K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']

Získání n-tého prvku sekvence:

from toolz.itertoolz import nth
 
values = [chr(i) for i in range(ord('A'), ord('Z')+1)]
 
print(values)
print(nth(0, values))
print(nth(25, values))
print(nth(26, values))

Výsledky:

['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
A
Z
Traceback (most recent call last):
  File "seq_nth.py", line 8, in <module>
    print(nth(26, values))
  File "/home/ptisnovs/.local/lib/python3.8/site-packages/toolz/itertoolz.py", line 396, in nth
    return seq[n]
IndexError: list index out of range
Poznámka: pro neplatný index prvku je tedy vyhazována výjimka.

Stejná operace, ale provedená pomocí get s uvedením výchozí hodnoty pro neznámé prvky:

from toolz.itertoolz import get
 
values = [chr(i) for i in range(ord('A'), ord('Z')+1)]
 
print(values)
print(get(0, values, "?"))
print(get(25, values, "?"))
print(get(26, values, "?"))

Výsledky:

['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
A
Z
?
Poznámka: pro neplatný index prvku je tedy vrácena specifikovaná výchozí hodnota.

6. Nekonečná sekvence s hodnotami vytvářenými s využitím uživatelské funkce

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 (realizovaného například pomocí funkce). Příkladem mohou být aritmetické, geometrické a další řady. V takovém případě lze pro vytvoření nekonečné sekvence použít funkci nazvanou příznačně iterate z balíčku toolz.itertoolz. 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 pochopitelně použít i uzávěr, tedy i možnost uložení mezivýsledků v uzávěru).

Podívejme se nyní na nejjednodušší možný příklad. Bude se jednat o generátor nekonečné aritmetické řady s krokem 1 a počátečním prvkem s nulovou hodnotou. Výpočet hodnoty n+1 prvku je realizován ve funkci nazvané inc:

from toolz.itertoolz import iterate, take
 
 
def inc(x):
    return x+1
 
 
sequence = iterate(inc, 0)
 
sequence = take(10, sequence)
print(list(sequence))

Výsledky získané po spuštění tohoto skriptu by měly vypadat následovně:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Pochopitelně můžeme v tomto případě použít i alternativní způsob zápisu založeného na anonymní funkci, což je kratší (a poněkud méně čitelné):

from toolz.itertoolz import iterate, take
 
 
sequence = iterate(lambda x: x+1, 0)
 
sequence = take(10, sequence)
print(list(sequence))

Ve třetím příkladu s funkcí iterate je ukázána řada numerických hodnot obsahujících celočíselné mocniny dvojky:

from toolz.itertoolz import iterate, take
 
 
def double(x):
    return x*2
 
 
sequence = iterate(double, 1)
 
sequence = take(10, sequence)
print(list(sequence))

A takto budou vypadat vypočtené výsledky uložené do výsledné sekvence:

[1, 2, 4, 8, 16, 32, 64, 128, 256, 512]

Taktéž si můžeme nechat vygenerovat sekvenci seznamů, v nichž postupně roste počet prvků (i jejich hodnoty):

from toolz.itertoolz import first, iterate, take
 
 
def nextval(x):
    return x + [x[-1]+1]
 
 
sequence = iterate(nextval, [1])
 
sequence = take(10, sequence)
print(list(sequence))

Výsledky jsem pro větší přehled ručně zarovnal:

[[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]]

7. Vygenerování Fibonacciho posloupnosti s využitím iterate

Poněkud komplikovanější je výpočet Fibonacciho posloupnosti s využitím stejné funkce, tedy funkce iterate. V tomto případě totiž musíme pracovat s dvojicí prvků s indexy n-1 a n pro výpočet prvku s indexem n+1. To sice funkce iterate přímo neumožňuje, ale je zde možné aplikovat malý trik – budeme předávat dvojici hodnot v jediném parametru typu n-tice (nebo seznam, dokonce by bylo možné použít i množinu):

from toolz.itertoolz import iterate, take
 
 
def one_step(p):
    return (p[1], p[0]+p[1])
 
 
sequence = iterate(one_step, (0, 1))
sequence = take(10, sequence)
print(list(sequence))

Tento demonstrační příklad vytiskne sekvenci dvojic prvků. Povšimněte si, že první hodnoty dvojic skutečně tvoří Fibonacciho posloupnost (a nutno dodat, že druhé prvky dvojic vlastně taky, pouze je posloupnost o jeden prvek posunuta):

[(0, 1), (1, 1), (1, 2), (2, 3), (3, 5), (5, 8), (8, 13), (13, 21), (21, 34), (34, 55)]

Malou úpravou tedy z této sekvence získáme skutečnou Fibonacciho posloupnost. Úprava spočívá v aplikaci funkce first na všechny dvojice:

from toolz.itertoolz import first, iterate, take
 
 
def one_step(p):
    return (p[1], p[0]+p[1])
 
 
sequence = iterate(one_step, (0, 1))
sequence = take(10, sequence)
print(list(map(first, sequence)))

Výsledek:

[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

8. Kombinace většího množství sekvencí s využitím funkce interleave

Další užitečnou 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 jak konečné, tak i nekonečné sekvence. Zkusme nejprve použít konečné sekvence:

from toolz.itertoolz import interleave, take
 
values1 = range(1, 11)
values2 = ["odd", "even"]*5
interleaved = interleave((values1, values2))
 
print(list(interleaved))

Výsledkem proložení je tato nová sekvence:

[1, 'odd', 2, 'even', 3, 'odd', 4, 'even', 5, 'odd', 6, 'even', 7, 'odd', 8, 'even', 9, 'odd', 10, 'even']

Otestujme si chování pro nestejně dlouhé sekvence:

from toolz.itertoolz import interleave, take
 
values1 = range(1, 16)
values2 = ["odd", "even"]*3
interleaved = interleave((values1, values2))
 
print(list(interleaved))

V tomto případě se nenahlásí chyba, pouze je výsledná sekvence doplněna prvky delší sekvence:

[1, 'odd', 2, 'even', 3, 'odd', 4, 'even', 5, 'odd', 6, 'even', 7, 8, 9, 10, 11, 12, 13, 14, 15]

9. Funkce interleave a nekonečné sekvence

Zajímavé bude zjistit chování funkce interleave pro nekonečné sekvence. Necháme si tedy proložit nekonečnou sekvenci s aritmetickou řadou celých čísel se sekvencí obsahující konečné množství prvků „odd“ a „even“. Výsledkem je nekonečná líná sekvence, z níž si necháme vypsat prvních dvacet prvků:

from toolz.itertoolz import iterate, interleave, take
 
 
def inc(x):
    return x+1
 
 
values1 = iterate(inc, 0)
values2 = ["odd", "even"]*5
interleaved = interleave((values1, values2))
 
print(list(take(20, interleaved)))

Výsledek by měl vypadat následovně:

[0, 'odd', 1, 'even', 2, 'odd', 3, 'even', 4, 'odd', 5, 'even', 6, 'odd', 7, 'even', 8, 'odd', 9, 'even']
Poznámka: pochopitelně získáme výsledek v konečném čase :-)

10. Rozdělení prvků sekvence do skupin s využití funkce groupby

Funkce nazvaná groupby (pozor – zde se zapisuje bez podtržítka) 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 typu filter či remove se zde tedy nejedná o predikát vracející pouze pravdivostní hodnotu, ale o funkci vracející libovolnou spočetnou hodnotu).

Poměrně dobrým a přitom krátkým demonstračním 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 toolz.itertoolz import groupby
 
values = range(100)
 
grouped = groupby(lambda x:x % 10, values)
 
for key, values in grouped.items():
    print(key, values)

Výsledkem bude deset sekvencí. V první sekvenci budou hodnoty bezezbytku dělitelné deseti, ve druhé sekvenci hodnoty se zbytkem 1 atd.:

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]

Funkci groupby 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 toolz.itertoolz import groupby
 
message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
words = message.split()
 
grouped = groupby(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 toolz.itertoolz import groupby
 
message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
words = message.split()
 
grouped = groupby(lambda x:len(x), words)
 
for key in sorted(grouped.keys()):
    print(key, grouped[key])

Výsledek:

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']

11. Groupby a nekonečné sekvence

Ve čtvrté kapitole jsme si řekli, že knihovna Toolz podporuje práci s nekonečnými sekvencemi. Aby se tyto sekvence mohly zpracovávat, je nutné realizovat líné vyhodnocování, tedy výpočet prvků sekvencí až ve chvíli, kdy je to skutečně nutné. Ovšem funkce groupby do této skupiny nepatří – není tedy líná. Ostatně si to můžete sami otestovat spuštěním následujícího příkladu:

from toolz.itertoolz import groupby, iterate, take
 
def inc(x):
    return x+1
 
 
values = iterate(inc, 0)
 
grouped = groupby(lambda x:x % 10, values)

Tento příklad bude pouze doplňovat další a další prvky do mapy generované funkcí groupby a skončí ve chvíli, kdy již nebude k dispozici dostatek operační paměti (takže příklad raději po pár sekundách zabijte příkazem kill, ať se nezačne swapovat).

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

Další funkcí, s níž se v dnešním článku seznámíme, je funkce nazvaná partition. Tato funkce rozdělí vstupní sekvenci do (obecně libovolného) množství výstupních sekvencí s tím, že tyto výstupní sekvence budou obsahovat n prvků specifikovaných při volání partition. Navíc je možné řídit, jakým způsobem se bude pracovat s prvky na konci vstupní sekvence, pokud její délka není celočíselně dělitelná onou hodnotou n. Ostatně si to ukažme na příkladu:

from toolz.itertoolz import partition
 
values = [chr(i) for i in range(ord('A'), ord('Z')+1)]
 
print(values)
print(list(partition(3, values)))
print(list(partition(3, values, "*")))

První volání funkce partition rozdělí znaky abecedy po trojicích, ovšem vynechá písmena na konci, které již nedokážou vytvořit trojici. Namísto toho druhé volání doplní znaky o „*“ a žádný vstupní znak se tak neztratí:

['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
[('A', 'B', 'C'), ('D', 'E', 'F'), ('G', 'H', 'I'), ('J', 'K', 'L'), ('M', 'N', 'O'), ('P', 'Q', 'R'), ('S', 'T', 'U'), ('V', 'W', 'X')]
[('A', 'B', 'C'), ('D', 'E', 'F'), ('G', 'H', 'I'), ('J', 'K', 'L'), ('M', 'N', 'O'), ('P', 'Q', 'R'), ('S', 'T', 'U'), ('V', 'W', 'X'), ('Y', 'Z', '*')]

13. Rozdělení nekonečné sekvence

Funkce partition popsaná v předchozí kapitole dokáže rozdělit i nekonečnou sekvenci, pochopitelně za předpokladu, že se nebudeme snažit zpracovat celý (nekonečný) výsledek. Můžeme si to snadno otestovat na sérii těchto kroků:

  1. Vytvoříme nekonečnou sekvenci celých čísel
  2. Rozdělíme tuto sekvenci do trojic (je jich taktéž nekonečně mnoho)
  3. Přečteme z této sekvence prvních 10 trojic
  4. Ty si necháme vypsat

Tyto kroky lze velmi snadno realizovat:

from toolz.itertoolz import iterate, partition, take
 
def inc(x):
    return x+1
 
 
values = iterate(inc, 0)
 
print(list(take(10, partition(3, values))))

A takto může vypadat výsledek:

[(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)]

14. Proložení prvků sekvence další hodnotou

Další funkcí, s níž se dnes seznámíme, je funkce nazvaná interpose. Tato funkce dokáže proložit prvky ze vstupní sekvence se zadanou hodnotou. To znamená, že výsledkem bude sekvence obsahující první prvek ze vstupní sekvence, zadanou hodnotu, druhý prvek ze vstupní sekvence, znovu zadanou hodnotu atd. Můžeme si například nechat proložit znaky abecedy hvězdičkou:

from toolz.itertoolz import interpose
 
values = [chr(i) for i in range(ord('A'), ord('Z')+1)]
 
print(values)
print("".join(interpose("*", values)))

Takto bude vypadat výsledek:

A*B*C*D*E*F*G*H*I*J*K*L*M*N*O*P*Q*R*S*T*U*V*W*X*Y*Z

Lze ovšem pracovat i s nekonečnými sekvencemi:

from toolz.itertoolz import iterate, interpose, take
 
def inc(x):
    return x+1
 
 
values = iterate(inc, 0)
 
print(list(take(20, interpose("*", values))))

Nyní bude prvních dvacet prvků výsledné sekvence vypadat následovně:

[0, '*', 1, '*', 2, '*', 3, '*', 4, '*', 5, '*', 6, '*', 7, '*', 8, '*', 9, '*']

15. Klasická funkce reduce i její paralelní varianta

V knihovně Toolz nalezneme i klasickou funkci reduce, která zde existuje kvůli snaze o zpětnou kompatibilitu. Ve skutečnosti se jedná o shodnou funkci, jakou nalezneme v balíčku functools. Použití tedy již známe:

from toolz import reduce
from toolz.itertoolz import take
 
 
def one_step(p, q):
    print(p, q)
    return p*q
 
 
result = reduce(one_step, range(1, 11), 1)
print(result)

Výsledkem bude hodnota faktoriálu pro n=10:

1 1
1 2
2 3
6 4
24 5
120 6
720 7
5040 8
40320 9
362880 10
3628800

Zajímavější je paralelní varianta funkce reduce, která je umístěna v podbalíčku sandbox.parallel. Tato varianta umožňuje souběžné mezivýpočty a tím pádem nezaručuje, v jakém pořadí se bude vstupní sekvence zpracovávat. To nám však pro komutativní operace nemusí vadit:

from toolz.sandbox.parallel import fold
from toolz.itertoolz import take
 
 
def one_step(p, q):
    print(p, q)
    return p*q
 
 
result = fold(one_step, range(1, 11), 1)
print(result)

16. Postupná redukce vstupu s akumulací mezivýsledků

Funkce accumulate má chování podobné výše popsané funkci reduce, ovšem s jedním podstatným rozdílem – zatímco v případě použití funkce reduce se dozvíme pouze celkový výsledek aplikace vybrané funkce na celou sekvenci, je u funkce accumulate vrácena sekvence všech mezivýsledků, čehož je možné v některých případech využít a opět tak eliminovat potřebu tvorby programových smyček. Vypočtěme si tedy tabulku faktoriálu pro n=1 až n=10:

from toolz.itertoolz import accumulate, take
 
 
def one_step(p, q):
    print(p, q)
    return p*q
 
 
sequence = accumulate(one_step, range(1, 11))
print(list(sequence))

Sekvence na konci skutečně obsahuje tabulku faktoriálů:

1 2
2 3
6 4
24 5
120 6
720 7
5040 8
40320 9
362880 10
[1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800]

17. Výpočet rozdílu mezi sekvencemi

Potenciálně velmi užitečnou funkcí je funkce nazvaná diff. Jak již jméno této funkce naznačuje, slouží pro zjištění rozdílů mezi vstupními sekvencemi. Ukažme si nejprve, jaký výsledek získáme pro dvě krátké vstupní sekvence, jejichž odpovídající si prvky mají někdy shodnou hodnotu a někdy naopak hodnotu rozdílnou:

from toolz.itertoolz import diff
 
 
seq1 = [1, 2, 3, 4, 5, 6, 7]
seq2 = [1, 0, 3, 4, 9, 9, 0]
 
print(list(diff(seq1, seq2)))

Výsledek obsahuje dvojice hodnot těch prvků, které jsou rozdílné. Nevíme tedy, jaké jsou indexy těchto prvků, ale známe jejich hodnoty:

[(2, 0), (5, 9), (6, 9), (7, 0)]

18. Rozdíly mezi větším množstvím sekvencí

Ve skutečnosti dokáže funkce diff najít rozdíly nikoli pouze mezi dvojicí vstupních sekvencí, ale mezi více sekvencemi. Přitom platí, že postačuje, aby se odlišoval jen jediný prvek na n-tém indexu pro to, aby byl hlášen rozdíl. Opět si to můžeme snadno vyzkoušet, a to na příkladu se třemi vstupními sekvencemi:

ict ve školství 24

from toolz.itertoolz import diff
 
 
seq1 = [1, 2, 3, 4, 5, 6, 7, 8]
seq2 = [1, 0, 3, 4, 9, 9, 0, 8]
seq3 = [1, 2, 3, 0, 0, 6, 7, 8]
 
print(list(diff(seq1, seq2, seq3)))

Povšimněte si, že hned v prvním případě jsou prvky ze dvou vstupních sekvencí shodné a liší se jen jeden prvek ze sekvence seq2. I to postačuje, aby byl detekován rozdíl:

[(2, 0, 2), (4, 4, 0), (5, 9, 0), (6, 9, 6), (7, 0, 7)]

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
       
105 count1.py nekonečná sekvence čítačů s hodnotami 0, 1, 2, … https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/count1.py
106 count2.py získání prvních dvaceti hodnot čítačů z původně nekonečné sekvence https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/count2.py
107 count3.py kombinace konečné a nekonečné sekvence s využitím standardní funkce zip https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/count3.py
108 count4.py kombinace dvou nekonečných sekvencí s využitím standardní funkce zip https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/count4.py
109 count5.py specifikace počáteční hodnoty nekonečné sekvence https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/count5.py
110 count6.py specifikace počáteční hodnoty a kroku nekonečné sekvence https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/count6.py
111 count7.py specifikace záporného kroku nekonečné sekvence https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/count7.py
112 count8.py neceločíselný krok i hodnota prvního prvku https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/count8.py
       
112 cycle1.py opakující se nekonečná sekvence dvou hodnot https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/cycle1.py
113 cycle2.py opakující se nekonečná sekvence dvou hodnot https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/cycle2.py
114 cycle3.py kombinace dvou opakujících se nekonečných sekvencí https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/cycle3.py
115 cycle4.py sekvence obsahující označení všech hracích karet https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/cycle4.py
       
116 group_by1.py rozdělení numerických hodnot do deseti skupin https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/group_by1.py
117 group_by2.py rozdělení slov do skupin podle délky https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/group_by2.py
118 group_by3.py rozdělení slov do skupin podle délky, výsledek je seřazen https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/group_by3.py
       
119 iterate1.py sekvence tvořená aritmetickou řadou https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/iterate1.py
120 iterate2.py sekvence tvořená aritmetickou řadou https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/iterate2.py
121 iterate3.py sekvence s celočíselnými mocninami dvojky https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/iterate3.py
122 iterate4.py vygenerování Fibonacciho posloupnosti (neúplné řešení) https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/iterate4.py
123 iterate5.py vygenerování Fibonacciho posloupnosti (úplné řešení) https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/iterate5.py
       
124 repeat1.py vygenerování konečné sekvence s deseti prvky https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/repeat1.py
125 repeat2.py vygenerování konečné sekvence s deseti prvky, převod sekvence na seznam https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/repeat2.py
126 repeat3.py vygenerování nekonečné sekvence bez její materializace https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/repeat3.py
127 repeat4.py vygenerování nekonečné sekvence s pokusem o její materializaci https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/repeat4.py
128 repeat5.py získání několika prvků z původně nekonečné sekvence https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/repeat5.py
129 repeat6.py kombinace konečné a nekonečné sekvence s využitím standardní funkce zip https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/repeat6.py
       
130 interleave.py kombinace prvků dvou nekonečných sekvencí https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/interleave.py
       
131 silent1.py výpočet podílu, funkce může vyhodit výjimku https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/silent1.py
132 silent2.py výpočet podílu, výjimka je zachycena přes @silent https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/silent2.py
133 silent3.py čtení ze souboru, funkce může vyhodit výjimku https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/silent3.py
134 silent4.py čtení ze souboru, výjimka je zachycena přes @silent https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/silent4.py
135 silent5.py explicitní vyhození výjimky s využitím raise https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/silent5.py
136 silent6.py explicitní vyhození výjimky s využitím raise, zachycení přes @silent https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/silent6.py
137 silent7.py explicitní vyhození výjimky ve volané funkci, opět zachycení přes @silent https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/silent7.py
       
138 ignore1.py zachycení výjimky typu Exception a od ní odvozených výjimek https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/ignore1.py
139 ignore2.py pokus o zachycení odlišné výjimky, než je ZeroDivisionError https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/ignore2.py
140 ignore3.py zachycení pouze jediné výjimky, která nás při výpočtu zajímá, tedy výjimky vyhození při dělení nulou https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/ignore3.py
141 ignore4.py vrácení zvolené hodnoty v případě, že je výjimka zachycena https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/ignore4.py
142 ignore5.py zachycení výjimky ZeroDivisionError, ignorace výjimky TypeError https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/ignore5.py
143 ignore6.py zachycení výjimky ZeroDivisionError a/nebo TypeError https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/ignore6.py
144 ignore7.py vrácení odlišných hodnot pro různé typy výjimek https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/ignore7.py
       
145 reraise1.py základní způsob použití dekorátoru @reraise https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/reraise1.py
146 reraise2.py reakce na odlišný typ výjimky https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/reraise2.py
147 reraise3.py reakce na větší množství typů výjimek https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/reraise3.py
148 reraise4.py použití @reraise, ovšem s prázdným parametrem errors https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/reraise4.py
149 reraise5.py využití informací z původní výjimky v nové výjimce https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/reraise5.py
       
150 retry1.py základní způsob použití dekorátoru @retry https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/retry1.py
151 retry2.py specifikace parametru timeout https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/retry2.py
152 retry3.py specifikace typu zachytávaných výjimek https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/retry3.py
153 retry4.py specifikace typu zachytávaných výjimek https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/retry4.py
154 retry5.py exponenciálně vzrůstající hodnota timeout https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/retry5.py
       
       
155 seq_first.py test operace first pro vstupní konečnou sekvenci https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/seq_first.py
156 seq_last.py test operace last pro vstupní konečnou sekvenci https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/seq_last.py
157 seq_take.py test operace take pro vstupní konečnou sekvenci https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/seq_take.py
158 seq_drop.py test operace drop pro vstupní konečnou sekvenci https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/seq_drop.py
159 seq_nth.py test operace nth pro vstupní konečnou sekvenci https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/seq_nth.py
160 seq_get.py test operace get pro vstupní konečnou sekvenci https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/seq_get.py
       
161 iterate1.py sekvence tvořená aritmetickou řadou, použití pojmenované funkce https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/iterate1.py
162 iterate2.py sekvence tvořená aritmetickou řadou, použití anonymní funkce https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/iterate2.py
163 iterate3.py sekvence s celočíselnými mocninami dvojky https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/iterate3.py
164 iterate4.py vygenerování Fibonacciho posloupnosti (neúplné řešení) https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/iterate4.py
165 iterate5.py vygenerování Fibonacciho posloupnosti (úplné řešení) https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/iterate5.py
166 iterate6.py vygenerování seznamů s aritmetickými řadami https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/iterate6.py
167 accumulate.py postupná redukce vstupu s akumulací mezivýsledků https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/accumulate.py
168 diff1.py výpočet rozdílu mezi dvěma sekvencemi https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/diff1.py
169 diff2.py výpočet rozdílu mezi třemi sekvencemi https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/diff2.py
170 group_by1.py operace groupby: rozdělení numerických hodnot do deseti skupin https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/group_by1.py
171 group_by2.py rozdělení slov do skupin podle délky https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/group_by2.py
172 group_by3.py rozdělení slov do skupin podle délky, výsledek je navíc seřazen https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/group_by3.py
173 group_by_infinite.py operace groupby nad nekonečnou sekvencí https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/grou­p_by_infinite.py
174 interleave.py kombinace většího množství sekvencí https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/interleave.py
175 interleave_length.py délka výsledné sekvence získaná po spojení sekvencí různé délky https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/in­terleave_length.py
176 interleave_infinite.py kombinace nekonečných sekvencí https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/in­terleave_infinite.py
177 interpose.py proložení prvků sekvence další hodnotou https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/interpose.py
178 partition.py rozdělení prvků sekvence do většího množství sekvencí pomocí https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/partition.py
179 partition_infinite.py rozdělení nekonečné sekvence https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/par­tition_infinite.py
180 reduce.py varianta funkce reduce https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/reduce.py
181 parallel_fold.py paralelní varianta funkce reduce https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/pa­rallel_fold.py

20. Odkazy na Internetu

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