Podpora funkcionálního programování v Pythonu: dynamický výběr (dispatch)

Dnes
Doba čtení: 62 minut

Sdílet

Autor: Root.cz s využitím DALL-E
Dnes se zaměříme na popis techniky nazvané dynamický výběr (dynamic dispatch) v Pythonu. Ve standardní knihovně je podporován single dispatch, a to jak pro funkce, tak i pro metody. Rozšířením této techniky vzniká multiple dispatch.

Podpora funkcionálního programování v Pythonu: dynamický výběr (dispatch)

Co se dozvíte v článku
  1. Podpora funkcionálního programování v Pythonu: dynamický výběr (dispatch)
  2. Dynamický výběr – dynamic dispatch
  3. Výběr na základě jediné hodnoty nebo více hodnot? single dispatch, multiple dispatch
  4. Krátké zopakování – standardní knihovna functools
  5. Dekorátor @singledispatch
  6. Úplný zdrojový kód prvního demonstračního příkladu, změna názvu funkce
  7. Rozpoznání parametru typu NoneType
  8. Varianty funkcí s plnými typovými informacemi
  9. Komplikovanější varianty využití dekorátoru @singledispatch
  10. Dekorátor @singledispatchmethod: dynamický výběr metody
  11. Základní způsob realizace dynamického výběru metody
  12. Kombinace dekorátorů @staticmethod a @singledispatchmethod
  13. Komplikovanější varianty využití dekorátoru @singledispatchmethod
  14. Dynamický výběr na základě typů většího množství parametrů volané funkce
  15. Balíček multipledispatch
  16. Příklady použití dekorátoru @dispatch
  17. Dynamický výběr a statické typové kontroly
  18. Statické typové kontroly a dekorátor @dispatch z balíčku multipledispatch
  19. Repositář s demonstračními příklady
  20. Odkazy na Internetu

Před třemi lety vycházel na Rootu krátký seriál Funkcionální programování v Pythonu, ve kterém jsme se zabývali různými funkcionálními technikami, které jsou dostupné pro multiparadigmatický jazyk Python. Tento jazyk se stal úspěšný mj. i proto, že se do značené míry dokáže přizpůsobit potřebám programátora. To v praxi znamená, že menší skripty a nástroje lze psát prakticky čistě imperativně (ovšem strukturovaně) a pro rozsáhlejší aplikace Python podporuje klasické třídně orientované objektově orientované programování (OOP).

To ovšem není vše, protože i v Pythonu nalezneme poměrně velké množství vlastností převzatých z funkcionálních jazyků (asi nejviditelnější vlastnost: funkce jsou zde plnohodnotnými typy a tím pádem jsou v Pythonu podporovány funkce vyššího řádu, lokální funkce atd. atd.) a dokonce pro něho vznikly knihovny primárně určené pro podporu funkcionálního přístupu (příkladem je funzy, toolz atd).

V seriálu jsme si popsali i mnoho funkcí a dekorátorů dostupných ve standardní knihovně functools. Dnes se zaměříme na popis programátorské techniky nazývané dynamický výběr (dynamic dispatch). Většinou se rozlišuje mezi dynamickým výběrem na základě jednoho (typicky prvního) parametru. V takovém případě se používá termín single dispatch. Podpora pro něj je součástí již výše zmíněné knihovny functools. Rozšířením této techniky vzniká multiple dispatch. Ten sice není ve standardní knihovně functools podporován, ale asi nebude velkým překvapením, že pro Python vznikly další knihovny, které multiple dispatch implementují. I s možnostmi těchto knihoven se dnes seznámíme.

Dynamický výběr – dynamic dispatch

V některých programovacích jazycích se můžeme setkat s termínem dynamický výběr (dynamic dispatch). Jedná se o techniku, která slouží k výběru nějaké polymorfní operace; typicky se jedná o volání funkce nebo metody, resp. přesněji řečeno o výběr varianty funkce nebo metody, která se má zavolat. Důležité přitom je, že tento výběr je proveden až v čase běhu aplikace (runtime) a nikoli už při překladu (compile time) nebo v případě Pythonu při načítání modulu s jeho průběžnou kompilací do bajtkódu.

V tomto článku se omezíme na dvě polymorfní operace, a to konkrétně na již zmíněný výběr volání funkcí a metod, a to na základě typu předávaného parametru nebo většího množství parametrů. Jedná se o takzvaný ad-hoc polymorfismus (každá varianta volané funkce nebo metody se totiž může chovat odlišně, na rozdíl od generických funkcí, které jsou příkladem parametrického polymorfismu).

Poznámka: v kontextu Pythonu znamená podpora dynamického výběru především to, že se (v mnoha případech) můžeme zbavit explicitních testů na typ, který je realizován funkcí isinstance() (i když je pravda, že nově můžeme použít pattern matching, který umožňuje ve vzorcích specifikovat právě datové typy).

Výběr na základě jediné hodnoty nebo více hodnot? single dispatch, multiple dispatch

V základní knihovně programovacího jazyka Python najdeme implementaci dynamického výběru na základě typu prvního parametru funkce nebo druhého parametru metody. Tato technika dynamického výběru se nazývá single dispatch a její výhodou je snadná implementace (s využitím slovníku). Další předností single dispatche je jednoduché rozhodování na základě typu (typy tvoří hierarchickou strukturu). Ovšem v některých programovacích jazycích, mezi které patří různé dialekty LISPu nebo jazyk Julia, se setkáme i s možností výběru funkce či metody na základě typů všech parametrů. Tato technika se – zcela logicky – nazývá multiple dispatch. Přímo v základních knihovnách Pythonu multiple dispatch sice nenalezneme, ovšem existuje hned několik jeho realizací ve formě knihovny, kterou je možné snadno nainstalovat a používat. Obecně ovšem platí, že multiple dispatch je pomalejší a mohou nastat problémy s výběrem správné funkce (s ohledem na hierarchii datových typů).

Krátké zopakování – standardní knihovna functools

V úvodní kapitole jsme se zmínili o existenci standardní knihovny nazvané functools, která vývojářům, kteří používají programovací jazyk Python, nabízí některé funkcionální techniky. Konkrétně jsme se seznámili s funkcí vyššího řádu nazvanou reduce, která je zde definována (což je ostatně zajímavé, protože její „sesterské“ funkce map a filter jsou umístěny ve výchozím jmenném prostoru Pythonu a není je tedy nutné importovat – jednoduše se dají přímo zavolat).

V knihovně functools nalezneme mnohé zajímavé funkce a dekorátory, jejichž jména i verze Pythonu, ve které byly uvedeny, jsou vypsány v tabulce:

Symbol Verze Pythonu
wraps 2.5
update_wrapper 2.5
partial 2.5
reduce 3.0
lru_cache 3.2
total_ordering 3.2
cmp_to_key 3.2
partialmethod 3.4
singledispatch 3.4
cached_property 3.8
singledispatchmethod 3.8
cache 3.9

Dnes nás budou zajímat pouze dekorátory singledispatch a singledispatchmethod.

Poznámka: jako dekorátor se v Pythonu označuje technika, která umožňuje snadno „obalit“ volání nějaké funkce dalším kódem a vrátit výsledek jako novou funkci s přidanými vlastnostmi. Označení „dekorátor“ vzniklo z toho důvodu, že se jméno dekorátoru (či dekorátorů) zapisuje před definici funkce nebo metody. Pozor: dekorátor v Pythonu je mnohem „mocnější“ technikou, než podobně zapisované anotace v Javě.

Dekorátor @singledispatch

V praktické části dnešního článku si nejdříve ukážeme, jakým způsobem se používá dekorátor nazvaný singledispatch (zapisuje se pochopitelně i se zavináčem na začátku):

singledispatch(func)
    Single-dispatch generic function decorator.
 
    Transforms a function into a generic function, which can have different
    behaviours depending upon the type of its first argument. The decorated
    function acts as the default implementation, and additional
    implementations can be registered using the register() attribute of the
    generic function.

V prvním demonstračním příkladu je definována jednoduchá funkce nazvaná function (což není rezervované klíčové slovo):

def function(arg):
    print("Original function with argument", arg, "that has type", type(arg))

Povšimněte si, že tato funkce akceptuje argument libovolného typu. Nyní tuto funkci obalíme dekorátorem @singledispatch:

from functools import singledispatch
 
 
@singledispatch
def function(arg):
    print("Original function with argument", arg, "that has type", type(arg))

Touto operací jsme získali novou funkci, která se ovšem chová dosti odlišným způsobem než původní funkce function! Nová funkce se taktéž používá jako dekorátor a umožňuje realizovat dynamický výběr na základě typu prvního (zde jediného) předaného parametru. Můžeme například rozlišit mezi voláním funkce s předáním parametru typu celé číslo, řetězec nebo seznam:

@function.register
def _(arg: int):
    print("Integer variant with argument:", arg)
 
 
@function.register
def _(arg: str):
    print("String variant with argument:", arg)
 
 
@function.register
def _(arg: list):
    print("List variant with argument:", arg)
Poznámka: jména těchto funkcí sice musí být uvedena, ale typicky se zde používá „nahrazovač“ (placeholder) představovaný v Pythonu podtržítkem.

Příklad volání této funkce – ve skutečnosti se volá jedna z definovaných variant a určení, o kterou variantu se jedná, je ponecháno až na čas běhu (runtime):

function(42)
function("foo")
function(["foo", "bar", "baz"])
function(1.4142)
function(None)

Výsledky by mohly vypadat následovně:

Integer variant with argument: 42
String variant with argument: foo
List variant with argument: ['foo', 'bar', 'baz']
Original function with argument 1.4142 that has type <class 'float'>
Original function with argument None that has type <class 'NoneType'>

V tomto případě se tedy zavolala první, druhá, třetí a následně dvakrát původní funkce.

Poznámka: povšimněte si, že jsme vůbec nemuseli používat OOP (protože dynamický výběr se sice v OOP používá, ovšem jedná se o obecnější techniku). Pouze jsme zkombinovali dekorátor a typové informace (type hints), které se již staly nedílnou součástí mnoha projektů vytvářených v Pythonu.

Úplný zdrojový kód prvního demonstračního příkladu, změna názvu funkce

Úplný zdrojový kód demonstračního příkladu z předchozí kapitoly vypadá následovně:

from functools import singledispatch
 
 
@singledispatch
def function(arg):
    print("Original function with argument", arg, "that has type", type(arg))
 
 
@function.register
def _(arg: int):
    print("Integer variant with argument:", arg)
 
 
@function.register
def _(arg: str):
    print("String variant with argument:", arg)
 
 
@function.register
def _(arg: list):
    print("List variant with argument:", arg)
 
 
function(42)
function("foo")
function(["foo", "bar", "baz"])
function(1.4142)
function(None)

Namísto jména function samozřejmě můžeme použít jakýkoli jiný platný identifikátor, například foo. Změní se jak jméno původní funkce, tak i všechny následující dekorátory:

from functools import singledispatch
 
 
@singledispatch
def foo(arg):
    print("Original function foo with argument", arg, "that has type", type(arg))
 
 
@foo.register
def _(arg: int):
    print("Integer variant with argument:", arg)
 
 
@foo.register
def _(arg: str):
    print("String variant with argument:", arg)
 
 
@foo.register
def _(arg: list):
    print("List variant with argument:", arg)
 
 
foo(42)
foo("foo")
foo(["foo", "bar", "baz"])
foo(1.4142)
foo(None)

Výsledky by se neměly odlišovat od prvního příkladu:

Integer variant with argument: 42
String variant with argument: foo
List variant with argument: ['foo', 'bar', 'baz']
Original function foo with argument 1.4142 that has type <class 'float'>
Original function foo with argument None that has type <class 'NoneType'>

Rozpoznání parametru typu NoneType

V programovacím jazyku Python se v hierarchii datových typů nachází i typ nazvaný NoneType, jehož jedinou hodnotou je None. I typ parametru nastaveného na None je snadné při dynamickém výběru rozpoznat, což si ukážeme v dalším demonstračním příkladu. Povšimněte si, že zapsaný typ je None a nikoli NoneType:

from functools import singledispatch
 
 
@singledispatch
def function(arg):
    print("Original function with argument", arg, "that has type", type(arg))
 
 
@function.register
def _(arg: int):
    print("Integer variant with argument:", arg)
 
 
@function.register
def _(arg: str):
    print("String variant with argument:", arg)
 
 
@function.register
def _(arg: list):
    print("List variant with argument:", arg)
 
 
@function.register
def _(arg: None):
    print("None variant with argument:", arg)
 
 
function(42)
function("foo")
function(["foo", "bar", "baz"])
function(1.4142)
function(None)

Po spuštění tohoto skriptu je zřejmé, že se skutečně v posledním případě zavolala korektní varianta funkce function:

Integer variant with argument: 42
String variant with argument: foo
List variant with argument: ['foo', 'bar', 'baz']
Original function with argument 1.4142 that has type <class 'float'>
None variant with argument: None

Varianty funkcí s plnými typovými informacemi

Do programovacího jazyka Python se postupně přidává (a navíc i neustále zlepšuje) podpora pro zápis takzvaných typových anotací resp. typových nápověd (type annotations, type hints). Jedná se o nová syntaktická pravidla v Pythonu umožňující nepovinnou (tj. do značné míry dobrovolnou) specifikaci typů parametrů funkcí a metod, typů návratových hodnot funkcí a metod, typů globálních i lokálních proměnných, typových parametrů u generických datových typů atd. Python sice umožňuje zápis typových anotací, ale (alespoň prozatím) neprovádí jejich kontrolu. Tu ponechává na jiných nástrojích, které jsou typicky založeny na statické analýze.

Přidání typových informací do Pythonu je (alespoň podle mínění autora tohoto článku) jedním z nejužitečnějších vylepšení tohoto jazyka. Podívejme se tedy, zda a jak je možné plné typové informace použít společně s dekorátorem @singledispatch. První varianta příkladu s přidanými typovými informacemi by mohla vypadat takto:

from typing import Any
 
from functools import singledispatch
 
 
@singledispatch
def function(arg: Any) -> None:
    print("Original function with argument", arg, "that has type", type(arg))
 
 
@function.register
def _(arg: int) -> None:
    print("Integer variant with argument:", arg)
 
 
@function.register
def _(arg: str) -> None:
    print("String variant with argument:", arg)
 
 
@function.register
def _(arg: list[Any]) -> None:
    print("List variant with argument:", arg)
 
 
@function.register
def _(arg: None) -> None:
    print("None variant with argument:", arg)
 
 
function(42)
function("foo")
function(["foo", "bar", "baz"])
function(1.4142)
function(None)

Zde ovšem nastává problém, a to typu list[Any] (což je mimochodem zcela korektní zápis typu):

Traceback (most recent call last):
  File "/home/ptisnovs/src/most-popular-python-libs/functools/single_dispatch_4.py", line 21, in <module>
    @function.register
     ^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.14t/functools.py", line 963, in register
    raise TypeError(
    ...<2 lines>...
    )
TypeError: Invalid annotation for 'arg'. list[typing.Any] is not a class.

V tomto případě je nutné použít malý trik – zapsat neúplnou typovou informaci přímo jako parametr dekorátoru. Nejedná se ovšem o příliš elegantní řešení:

from typing import Any
 
from functools import singledispatch
 
 
@singledispatch
def function(arg: Any) -> None:
    print("Original function with argument", arg, "that has type", type(arg))
 
 
@function.register
def _(arg: int) -> None:
    print("Integer variant with argument:", arg)
 
 
@function.register
def _(arg: str) -> None:
    print("String variant with argument:", arg)
 
 
@function.register(list)
def _(arg: list[Any]) -> None:
    print("List variant with argument:", arg)
 
 
@function.register
def _(arg: None) -> None:
    print("None variant with argument:", arg)
 
 
function(42)
function("foo")
function(["foo", "bar", "baz"])
function(1.4142)
function(None)

Výsledky získané po spuštění tohoto příkladu, které ukazují, jaká varianta funkce se ve skutečnosti volá, vypadají následovně:

Integer variant with argument: 42
String variant with argument: foo
List variant with argument: ['foo', 'bar', 'baz']
Original function with argument 1.4142 that has type <class 'float'>
None variant with argument: None

Komplikovanější varianty využití dekorátoru @singledispatch

Dekorátor @singledispatch lze využít v různých situacích. V dalším demonstračním příkladu je ukázána jeho aplikace na funkci, která akceptuje dva parametry. Výběr, která varianta funkce se skutečně zavolá, je však stále založen pouze na základě typu prvního předávaného parametru:

from typing import Any
 
from functools import singledispatch
 
 
@singledispatch
def function(arg: Any, second: int) -> None:
    print("Original function with argument", arg, "that has type", type(arg))
 
 
@function.register
def _(arg: int, second: int) -> None:
    print("Integer variant with argument:", arg)
 
 
@function.register
def _(arg: str, second: int) -> None:
    print("String variant with argument:", arg)
 
 
@function.register(list)
def _(arg: list[Any], second: int) -> None:
    print("List variant with argument:", arg)
 
 
@function.register
def _(arg: None, second: int) -> None:
    print("None variant with argument:", arg)
 
 
function(42, 0)
function("foo", 0)
function(["foo", "bar", "baz"], 0)
function(1.4142, 0)
function(None, 0)

Způsob volání jednotlivých variant funkce s předáním parametrů:

Integer variant with argument: 42
String variant with argument: foo
List variant with argument: ['foo', 'bar', 'baz']
Original function with argument 1.4142 that has type <class 'float'>
None variant with argument: None

Díky tomu, že je plně podporován typový systém jazyka Python, tj. včetně sjednocení datových typů (union), můžeme zajistit dynamický výběr funkce, která například akceptuje buď celé číslo nebo řetězec atd. To je ukázáno v dalším příkladu:

from typing import Any
 
from functools import singledispatch
 
 
@singledispatch
def function(arg: Any) -> None:
    print("Original function with argument", arg, "that has type", type(arg))
 
 
@function.register
def _(arg: int | str) -> None:
    print("Integer variant with int or str argument:", arg)
 
 
@function.register(list | tuple)
def _(arg: list[Any] | tuple[Any, ...]) -> None:
    print("List or tuple variant with argument:", arg)
 
 
@function.register
def _(arg: None) -> None:
    print("None variant with argument:", arg)
 
 
function(42)
function("foo")
function(["foo", "bar", "baz"])
function(("foo", "bar", "baz"))
function(1.4142)
function(None)

Výsledky ukazují, jak se union vyhodnotil pro konkrétní volání funkce:

Integer variant with int or str argument: 42
Integer variant with int or str argument: foo
List or tuple variant with argument: ['foo', 'bar', 'baz']
List or tuple variant with argument: ('foo', 'bar', 'baz')
Original function with argument 1.4142 that has type <class 'float'>
None variant with argument: None

A konečně se podívejme, jak se vlastně funkce realizující dynamický výběr přeloží do bajtkódu Pythonu:

from typing import Any
import dis
 
from functools import singledispatch
 
 
@singledispatch
def function(arg: Any) -> None:
    print("Original function with argument", arg, "that has type", type(arg))
 
 
@function.register
def _(arg: int) -> None:
    print("Integer variant with argument:", arg)
 
 
@function.register
def _(arg: str) -> None:
    print("String variant with argument:", arg)
 
 
@function.register(list)
def _(arg: list[Any]) -> None:
    print("List variant with argument:", arg)
 
 
@function.register
def _(arg: None) -> None:
    print("None variant with argument:", arg)
 
 
dis.dis(function)

Výsledný bajtkód je relativně složitý, ovšem ukazuje se, že se skutečně volá kód pro realizaci dynamického výběru:

  --           COPY_FREE_VARS           2

 978           RESUME                   0

 979           LOAD_FAST_BORROW         0 (args)
               TO_BOOL
               POP_JUMP_IF_TRUE        15 (to L1)
               NOT_TAKEN

 980           LOAD_GLOBAL              1 (TypeError + NULL)
               LOAD_DEREF               3 (funcname)
               FORMAT_SIMPLE
               LOAD_CONST               0 (' requires at least 1 positional argument')
               BUILD_STRING             2
               CALL                     1
               RAISE_VARARGS            1

 982   L1:     LOAD_DEREF               2 (dispatch)
               PUSH_NULL
               LOAD_FAST_BORROW         0 (args)
               LOAD_SMALL_INT           0
               BINARY_OP               26 ([])
               LOAD_ATTR                2 (__class__)
               CALL                     1
               PUSH_NULL
               LOAD_FAST_BORROW         0 (args)
               BUILD_MAP                0
               LOAD_FAST_BORROW         1 (kw)
               DICT_MERGE               1
               CALL_FUNCTION_EX
               RETURN_VALUE

Ještě se přesvědčíme o tom, jakým způsobem je zobrazen stack trace při vzniku výjimky v dynamicky vybrané funkci:

from typing import Any
import dis
 
from functools import singledispatch
 
 
@singledispatch
def function(arg: Any) -> None:
    print("Original function with argument", arg, "that has type", type(arg))
 
 
@function.register
def _(arg: int) -> None:
    print("Integer variant with argument:", arg)
 
 
@function.register
def _(arg: str) -> None:
    print("String variant with argument:", arg)
 
 
@function.register(list)
def _(arg: list[Any]) -> None:
    print("List variant with argument:", arg)
 
 
@function.register
def _(arg: None) -> None:
    raise Exception("why not")
 
 
function(None)

Výsledek sice není příliš čitelný, ovšem odhalí korektní strack trace (viz čísla řádků), což je v praxi velmi důležité:

Traceback (most recent call last):
  File "/home/ptisnovs/src/most-popular-python-libs/functools/single_dispatch_9.py", line 32, in <module>
    function(None)
    ~~~~~~~~^^^^^^
  File "/usr/local/lib/python3.14t/functools.py", line 982, in wrapper
    return dispatch(args[0].__class__)(*args, **kw)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
  File "/home/ptisnovs/src/most-popular-python-libs/functools/single_dispatch_9.py", line 29, in _
    raise Exception("why not")
Exception: why not

Dekorátor @singledispatchmethod: dynamický výběr metody

Prozatím jsme si ukázali způsoby využití dekorátoru nazvaného @singledispatch, který se používá pro dynamický výběr variant běžných funkcí. Ovšem u metod je nutné použít odlišný dekorátor, konkrétně dekorátor nazvaný @singledispatchmethod. Proč ale vůbec potřebujeme odlišný dekorátor? Prvním parametrem metody je totiž self (reference na objekt, jehož metoda se volá) a pro rozlišení varianty metody je tedy nutné použít druhý parametr, resp. jeho typ:

class singledispatchmethod(builtins.object)
 |  singledispatchmethod(func)
 |
 |  Single-dispatch generic method descriptor.
 |
 |  Supports wrapping existing descriptors and handles non-descriptor
 |  callables as instance methods.
 |
 |  Methods defined here:
 |
 |  __get__(self, obj, cls=None)
 |
 |  __init__(self, func)
 |      Initialize self.  See help(type(self)) for accurate signature.
 |
 |  __repr__(self)
 |      Return repr(self).
 |
 |  register(self, cls, method=None)
 |      generic_method.register(cls, func) -> func
 |
 |      Registers a new implementation for the given *cls* on a *generic_method*.
 ...
 ...
 ...

Základní způsob realizace dynamického výběru metody

Dekorátor @singledispatchmethod se používá stejně snadno, jako již popsaný dekorátor @singledispatch. Vyzkoušejme si jeho použití na metodě nazvané foo. Povšimněte si, že rozhodnutí o tom, které konkrétní varianta této metody se zavolá, je provedeno na základě typu druhého parametru, protože prvním parametrem je self:

from functools import singledispatchmethod
 
 
class FooClass:
 
    @singledispatchmethod
    def foo(self, arg):
        print("Original foo method with argument", arg, "that has type", type(arg))
 
 
    @foo.register
    def _(self, arg: int):
        print("Integer variant with argument:", arg)
 
 
    @foo.register
    def _(self, arg: str):
        print("String variant with argument:", arg)
 
 
    @foo.register
    def _(self, arg: list):
        print("List variant with argument:", arg)
 
 
f = FooClass()
f.foo(42)
f.foo("foo")
f.foo(["foo", "bar", "baz"])
f.foo(1.4142)
f.foo(None)

Chování skriptu po jeho spuštění:

Integer variant with argument: 42
String variant with argument: foo
List variant with argument: ['foo', 'bar', 'baz']
Original foo method with argument 1.4142 that has type <class 'float'>
Original foo method with argument None that has type <class 'NoneType'>

Kombinace dekorátorů @staticmethod a @singledispatchmethod

Pozor si ovšem musíme dát při kombinaci dekorátorů @singledispatchmethod a @staticmethod (jde o označení statické metody, které se tedy nepředává parametr self). Oba tyto dekorátory je možné kombinovat, což je užitečné, ovšem musíme si dát pozor na pořadí aplikace dekorátorů (připomeňme si, že dekorátor metodu transformuje do jiné metody, tedy druhý dekorátor je aplikován jako první). Nejprve si ukažme metody s dekorátory v pořadí dispatch+staticmethod:

from functools import singledispatchmethod
 
 
class FooClass:
 
    @singledispatchmethod
    @staticmethod
    def foo(arg):
        print("Original foo method with argument", arg, "that has type", type(arg))
 
 
    @foo.register
    @staticmethod
    def _(arg: int):
        print("Integer variant with argument:", arg)
 
 
    @foo.register
    @staticmethod
    def _(arg: str):
        print("String variant with argument:", arg)
 
 
    @foo.register
    @staticmethod
    def _(arg: list):
        print("List variant with argument:", arg)
 
 
f = FooClass()
f.foo(42)
f.foo("foo")
f.foo(["foo", "bar", "baz"])
f.foo(1.4142)
f.foo(None)

Tento příklad bude bez problémů spustitelný:

Integer variant with argument: 42
String variant with argument: foo
List variant with argument: ['foo', 'bar', 'baz']
Original foo method with argument 1.4142 that has type <class 'float'>
Original foo method with argument None that has type <class 'NoneType'>

Co se ovšem stane v případě, že pořadí aplikace dekorátorů prohodíme?

from functools import singledispatchmethod
 
 
class FooClass:
 
    @staticmethod
    @singledispatchmethod
    def foo(arg):
        print("Original foo method with argument", arg, "that has type", type(arg))
 
 
    @staticmethod
    @foo.register
    def _(arg: int):
        print("Integer variant with argument:", arg)
 
 
    @staticmethod
    @foo.register
    def _(arg: str):
        print("String variant with argument:", arg)
 
 
    @staticmethod
    @foo.register
    def _(arg: list):
        print("List variant with argument:", arg)
 
 
f = FooClass()
f.foo(42)
f.foo("foo")
f.foo(["foo", "bar", "baz"])
f.foo(1.4142)
f.foo(None)

Nyní dojde už při načítání modulu k vyhození výjimky:

  File "/home/ptisnovs/src/most-popular-python-libs/functools/single_dispatch_method_3.py", line 4, in <module>
    class FooClass:
    ...<22 lines>...
            print("List variant with argument:", arg)
  File "/home/ptisnovs/src/most-popular-python-libs/functools/single_dispatch_method_3.py", line 13, in FooClass
    @foo.register
     ^^^^^^^^^^^^
AttributeError: 'staticmethod' object has no attribute 'register'

Komplikovanější varianty využití dekorátoru @singledispatchmethod

Samozřejmě si můžeme otestovat i další možnosti využití dekorátoru @singledispatchmethod. Nejprve pro metodu s plně definovanými typy argumentů i návratové hodnoty:

from typing import Any
 
from functools import singledispatchmethod
 
class FooClass:
 
    @singledispatchmethod
    def foo(self, arg: Any) -> None:
        print("Original function with argument", arg, "that has type", type(arg))
 
 
    @foo.register
    def _(self, arg: int | str) -> None:
        print("Integer or string variant with int or str argument:", arg)
 
 
    @foo.register(list | tuple)
    def _(self, arg: list[Any] | tuple[Any, ...]) -> None:
        print("List or tuple variant with argument:", arg)
 
 
    @foo.register
    def _(self, arg: None) -> None:
        print("None variant with argument:", arg)
 
 
f = FooClass()
f.foo(42)
f.foo("foo")
f.foo(["foo", "bar", "baz"])
f.foo(("foo", "bar", "baz"))
f.foo(1.4142)
f.foo(None)

Výsledky:

Integer or string variant with int or str argument: 42
Integer or string variant with int or str argument: foo
List or tuple variant with argument: ['foo', 'bar', 'baz']
List or tuple variant with argument: ('foo', 'bar', 'baz')
Original function with argument 1.4142 that has type <class 'float'>
None variant with argument: None

A konečně specifikace vlastní třídy (tedy vlastně nového datového typu) pro parametr předávaný do metody:

from typing import Any
 
from functools import singledispatchmethod
 
class BarClass:
    def __init__(self, value: int):
        self.value = value
 
 
class FooClass:
 
    @singledispatchmethod
    def foo(self, arg: Any) -> None:
        print("Original function with argument", arg, "that has type", type(arg))
 
 
    @foo.register
    def _(self, arg: int | str) -> None:
        print("Integer or string variant with int or str argument:", arg)
 
 
    @foo.register(list | tuple)
    def _(self, arg: list[Any] | tuple[Any, ...]) -> None:
        print("List or tuple variant with argument:", arg)
 
 
    @foo.register
    def _(self, arg: BarClass) -> None:
        print("Bar variant with argument:", arg.value)
 
 
    @foo.register
    def _(self, arg: None) -> None:
        print("None variant with argument:", arg)
 
 
f = FooClass()
f.foo(42)
f.foo("foo")
f.foo(["foo", "bar", "baz"])
f.foo(("foo", "bar", "baz"))
f.foo(BarClass(42))
f.foo(1.4142)
f.foo(None)

Opět se podívejme na vypsané výsledky, zejména na zvýrazněný řádek:

Integer or string variant with int or str argument: 42
Integer or string variant with int or str argument: foo
List or tuple variant with argument: ['foo', 'bar', 'baz']
List or tuple variant with argument: ('foo', 'bar', 'baz')
Bar variant with argument: 42
Original function with argument 1.4142 that has type <class 'float'>
None variant with argument: None

Dynamický výběr na základě typů většího množství parametrů volané funkce

Základní knihovna programovacího jazyka Python, konkrétně balíček functools, podporuje pouze výše uvedenou techniku nazvanou single dispatch. To znamená, že pro rozhodnutí, kterou variantu funkce zavolat, se zjišťuje typ prvního parametru funkce nebo typ druhého parametru metody (první parametr metody totiž vybírá samotný objekt). Pro většinu účelů je tento způsob dostačující, ovšem jiné programovací jazyky (například Julia a Clojure) podporují i multiple dispatch. Jedná se o silnou programovací techniku, takže není divem, že podobný způsob byl nakonec realizován i v Pythonu. Vniklo dokonce několik implementací, například:

  1. Plum: Multiple Dispatch in Python
    https://pypi.org/project/plum-dispatch/
  2. multimethod
    https://pypi.org/project/multimethod/
  3. multimethod-dispatcher
    https://pypi.org/project/multimethod-dispatcher/
  4. multipledispatch
    https://pypi.org/project/mul­tipledispatch/
Poznámka: ve skutečnosti zcela jistě bude podobných balíčků větší množství; vypsal jsem jen ty, které jsou vhodné pro reálné použití.

Balíček multipledispatch

V závěrečné části dnešního článku si ukážeme základní způsoby použití balíčku multipledispatch. Nejedná se o balíček ze základní knihovny Pythonu, což znamená, že je nutné ho doinstalovat, například s využitím pip, pdm, uv atd.:

$ uv add multipledispatch
 
Using CPython 3.13.9 interpreter at: /usr/bin/python3.13
Creating virtual environment at: .venv
Resolved 2 packages in 279ms
Prepared 1 package in 107ms
Installed 1 package in 4ms
 + multipledispatch==1.0.0

Tento balíček se zapíše i do projektového souboru pyproject.toml:

[project]
name = "dispatch-demo"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
    "multipledispatch>=1.0.0",
]

Ještě se pro změnu přesvědčíme o tom, že tento balíček si s sebou nepřinesl žádné další závislosti:

$ uv tree
 
Resolved 2 packages in 1ms
dispatch-demo v0.1.0
└── multipledispatch v1.0.0

V balíčku multipledispatch je deklarován dekorátor nazvaný (což je možná poněkud překvapivé) @dispatch:

dispatch(*types, **kwargs)
    Dispatch function on the types of the inputs
 
    Supports dispatch on all non-keyword arguments.
 
    Collects implementations based on the function name.  Ignores namespaces.
 
    If ambiguous type signatures occur a warning is raised when the function is
    defined suggesting the additional method to break the ambiguity.
 
    Examples
    --------
 
    >>> @dispatch(int)
    ... def f(x):
    ...     return x + 1
 
    >>> @dispatch(float)
    ... def f(x):
    ...     return x - 1
 
    >>> f(3)
    4
    >>> f(3.0)
    2.0
 
    Specify an isolated namespace with the namespace keyword argument

Příklady použití dekorátoru @dispatch

Dekorátor @dispatch se používá odlišným způsobem, než výše popsané dekorátory @singledispatch a @singledispatchmethod. Všechny varianty funkce (se stejným jménem) jsou obaleny tím stejným dekorátorem, který jako svůj parametr obsahuje typ či typy argumentů:

from multipledispatch import dispatch
 
@dispatch(int)
def function(arg: int):
    print("Integer variant with argument:", arg)
 
 
@dispatch(str)
def function(arg: str):
    print("String variant with argument:", arg)
 
 
@dispatch(list)
def function(arg: list):
    print("List variant with argument:", arg)
 
 
@dispatch(object)
def function(arg: object):
    print("Original function with argument", arg, "that has type", type(arg))
 
 
function(42)
function("foo")
function(["foo", "bar", "baz"])
function(1.4142)
function(None)

Ověření chování v čase běhu (runtime):

$ uv run multiple_dispatch_1.py 
 
Integer variant with argument: 42
String variant with argument: foo
List variant with argument: ['foo', 'bar', 'baz']
Original function with argument 1.4142 that has type <class 'float'>
Original function with argument None that has type <class 'NoneType'>

Ovšem pochopitelně je možné definovat více typů pro větší množství argumentů:

from multipledispatch import dispatch
 
@dispatch(int)
def function(arg: int):
    print("Integer variant with argument:", arg)
 
 
@dispatch(int, int)
def function(arg1: int, arg2: int):
    print("Integer variant with two arguments:", arg1, arg2)
 
 
@dispatch(str)
def function(arg: str):
    print("String variant with argument:", arg)
 
 
@dispatch(str, int)
def function(arg1: str, arg2: int):
    print("String+int variant with arguments:", arg1, arg2)
 
 
@dispatch(list)
def function(arg: list):
    print("List variant with argument:", arg)
 
 
@dispatch(object)
def function(arg: object):
    print("Original function with argument", arg, "that has type", type(arg))
 
 
function(42)
function(42, 0)
function("foo")
function("foo", 42)
function(["foo", "bar", "baz"])
function(1.4142)
function(None)

Opět se podívejme na výsledky:

$ uv run multiple_dispatch_2.py
 
Integer variant with argument: 42
Integer variant with two arguments: 42 0
String variant with argument: foo
String+int variant with arguments: foo 42
List variant with argument: ['foo', 'bar', 'baz']
Original function with argument 1.4142 that has type <class 'float'>
Original function with argument None that has type <class 'NoneType'>

Ověření, které varianty funkce se vyberou v případě, že funkce akceptuje tři parametry různých typů:

from multipledispatch import dispatch
 
@dispatch(int, int, int)
def function(arg1: int, arg2: int, arg3: int):
    print("Variant [int, int, int]")
 
@dispatch(str, int, int)
def function(arg1: str, arg2: int, arg3: int):
    print("Variant [str, int, int]")
 
@dispatch(int, str, int)
def function(arg1: int, arg2: str, arg3: int):
    print("Variant [int, str, int]")
 
@dispatch(int, int, str)
def function(arg1: int, arg2: int, arg3: str):
    print("Variant [int, int, str]")
 
 
 
function(1, 2, 3)
function("foo", 2, 3)
function(1, "bar", 3)
function(1, 2, "baz")
function("foo", 2, "baz")

Výsledky (včetně chyby v posledním případě – tato chyba byla očekávána):

$ uv run multiple_dispatch_3.py
 
Variant [int, int, int]
Variant [str, int, int]
Variant [int, str, int]
Variant [int, int, str]
Traceback (most recent call last):
  File "/tmp/ramdisk/dispatch-demo/.venv/lib64/python3.13/site-packages/multipledispatch/dispatcher.py", line 269, in __call__
    func = self._cache[types]
           ~~~~~~~~~~~^^^^^^^
KeyError: (<class 'str'>, <class 'int'>, <class 'str'>)
 
During handling of the above exception, another exception occurred:
 
Traceback (most recent call last):
  File "/tmp/ramdisk/dispatch-demo/multiple_dispatch_3.py", line 26, in <module>
    function("foo", 2, "baz")
    ~~~~~~~~^^^^^^^^^^^^^^^^^
  File "/tmp/ramdisk/dispatch-demo/.venv/lib64/python3.13/site-packages/multipledispatch/dispatcher.py", line 273, in __call__
    raise NotImplementedError(
    ...<2 lines>...
    )
NotImplementedError: Could not find signature for function: <str, int, str>

Dynamický výběr a statické typové kontroly

V závěrečné části dnešního článku si ještě ukážeme, jakým způsobem a do jaké míry je možné kombinovat dynamický výběr se statickými typovými kontrolami a tedy i se zápisem type hintů ve zdrojových kódech.

Začneme zdrojovým kódem s dekorátorem @singledispatch, ovšem bez úplných typových informací:

from functools import singledispatch
 
 
@singledispatch
def function(arg):
    print("Original function with argument", arg, "that has type", type(arg))
 
 
@function.register
def _(arg: int):
    print("Integer variant with argument:", arg)
 
 
@function.register
def _(arg: str):
    print("String variant with argument:", arg)
 
 
@function.register
def _(arg: list):
    print("List variant with argument:", arg)
 
 
function(42)
function("foo")
function(["foo", "bar", "baz"])
function(1.4142)
function(None)

Statická (a navíc striktní) typová kontrola nástrojem mypy dopadne následovně:

$ uv run mypy --strict single_dispatch_1.py
 
single_dispatch_1.py:5: error: Function is missing a type annotation  [no-untyped-def]
single_dispatch_1.py:10: error: Function is missing a return type annotation  [no-untyped-def]
single_dispatch_1.py:15: error: Function is missing a return type annotation  [no-untyped-def]
single_dispatch_1.py:20: error: Function is missing a return type annotation  [no-untyped-def]
single_dispatch_1.py:20: error: Missing type parameters for generic type "list"  [type-arg]
Found 5 errors in 1 file (checked 1 source file)

Varianta příkladu s úplnými typovými informacemi:

from typing import Any
 
from functools import singledispatch
 
 
@singledispatch
def function(arg: Any) -> None:
    print("Original function with argument", arg, "that has type", type(arg))
 
 
@function.register
def _(arg: int) -> None:
    print("Integer variant with argument:", arg)
 
 
@function.register
def _(arg: str) -> None:
    print("String variant with argument:", arg)
 
 
@function.register(list)
def _(arg: list[Any]) -> None:
    print("List variant with argument:", arg)
 
 
@function.register
def _(arg: None) -> None:
    print("None variant with argument:", arg)
 
 
function(42)
function("foo")
function(["foo", "bar", "baz"])
function(1.4142)
function(None)

Nyní není při statické typové kontrole žádný problém nalezen, což je ostatně jen dobře:

$ uv run mypy --strict single_dispatch_5.py
 
Success: no issues found in 1 source file

Zdrojový kód s typovými informacemi obsahujícími i sofistikovanější datové typy (union atd.):

from typing import Any
import dis
 
from functools import singledispatch
 
 
@singledispatch
def function(arg: Any) -> None:
    print("Original function with argument", arg, "that has type", type(arg))
 
 
@function.register
def _(arg: int | str) -> None:
    print("Integer variant with int or str argument:", arg)
 
 
@function.register(list | tuple)
def _(arg: list[Any] | tuple[Any, ...]) -> None:
    print("List or tuple variant with argument:", arg)
 
 
@function.register
def _(arg: None) -> None:
    print("None variant with argument:", arg)
 
 
function(42)
function("foo")
function(["foo", "bar", "baz"])
function(("foo", "bar", "baz"))
function(1.4142)
function(None)

Výsledky typové kontroly opět dopadnou (podle očekávání) velmi dobře:

$ uv run mypy --strict single_dispatch_7.py
 
Success: no issues found in 1 source file

Totéž si můžeme vyzkoušet i pro dekorátor @singledispatchmethod. Nejprve pro programový kód bez plných typových informací:

from functools import singledispatchmethod
 
 
class FooClass:
 
    @singledispatchmethod
    def foo(self, arg):
        print("Original foo method with argument", arg, "that has type", type(arg))
 
 
    @foo.register
    def _(self, arg: int):
        print("Integer variant with argument:", arg)
 
 
    @foo.register
    def _(self, arg: str):
        print("String variant with argument:", arg)
 
 
    @foo.register
    def _(self, arg: list):
        print("List variant with argument:", arg)
 
 
f = FooClass()
f.foo(42)
f.foo("foo")
f.foo(["foo", "bar", "baz"])
f.foo(1.4142)
f.foo(None)

Statická typová kontrola nalezne (podle očekávání) několik problémů:

$ uv run mypy --strict single_dispatch_method_1.py
 
single_dispatch_method_1.py:7: error: Function is missing a type annotation  [no-untyped-def]
single_dispatch_method_1.py:12: error: Function is missing a return type annotation  [no-untyped-def]
single_dispatch_method_1.py:17: error: Function is missing a return type annotation  [no-untyped-def]
single_dispatch_method_1.py:22: error: Function is missing a return type annotation  [no-untyped-def]
single_dispatch_method_1.py:22: error: Missing type parameters for generic type "list"  [type-arg]
Found 5 errors in 1 file (checked 1 source file)

Ve druhém příkladu do kódu doplníme plné typové informace:

from typing import Any
 
from functools import singledispatchmethod
 
class FooClass:
 
    @singledispatchmethod
    def foo(self, arg: Any) -> None:
        print("Original function with argument", arg, "that has type", type(arg))
 
 
    @foo.register
    def _(self, arg: int | str) -> None:
        print("Integer or string variant with int or str argument:", arg)
 
 
    @foo.register(list | tuple)
    def _(self, arg: list[Any] | tuple[Any, ...]) -> None:
        print("List or tuple variant with argument:", arg)
 
 
    @foo.register
    def _(self, arg: None) -> None:
        print("None variant with argument:", arg)
 
 
f = FooClass()
f.foo(42)
f.foo("foo")
f.foo(["foo", "bar", "baz"])
f.foo(("foo", "bar", "baz"))
f.foo(1.4142)
f.foo(None)

Výsledky statické typové kontroly:

$ uv run mypy --strict single_dispatch_method_4.py
 
Success: no issues found in 1 source file

A nakonec si ukažme příklad rozšířený o vlastní nový datový typ představovaný třídou BarClass:

from typing import Any
 
from functools import singledispatchmethod
 
class BarClass:
    def __init__(self, value: int):
        self.value = value
 
 
class FooClass:
 
    @singledispatchmethod
    def foo(self, arg: Any) -> None:
        print("Original function with argument", arg, "that has type", type(arg))
 
 
    @foo.register
    def _(self, arg: int | str) -> None:
        print("Integer or string variant with int or str argument:", arg)
 
 
    @foo.register(list | tuple)
    def _(self, arg: list[Any] | tuple[Any, ...]) -> None:
        print("List or tuple variant with argument:", arg)
 
 
    @foo.register
    def _(self, arg: BarClass) -> None:
        print("Bar variant with argument:", arg.value)
 
 
    @foo.register
    def _(self, arg: None) -> None:
        print("None variant with argument:", arg)
 
 
f = FooClass()
f.foo(42)
f.foo("foo")
f.foo(["foo", "bar", "baz"])
f.foo(("foo", "bar", "baz"))
f.foo(BarClass(42))
f.foo(1.4142)
f.foo(None)

Ani v tomto případě statická typová kontrola neodhalí žádné problémy:

$ uv run mypy --strict single_dispatch_method_5.py
 
Success: no issues found in 1 source file

Statické typové kontroly a dekorátor @dispatch z balíčku multipledispatch

Z příkladů uvedených v předchozí kapitole bylo patrné, že standardní dekorátory @singledispatch a @singledispatchmethod je možné bez problémů zkombinovat se zápisem typových informací. Ovšem jak je tomu v případě balíčku multipledispatch a jeho dekorátoru @dispatch? To si ověříme v této kapitole.

První příklad bez úplných typových informací:

from multipledispatch import dispatch
 
@dispatch(int)
def function(arg: int):
    print("Integer variant with argument:", arg)
 
 
@dispatch(str)
def function(arg: str):
    print("String variant with argument:", arg)
 
 
@dispatch(list)
def function(arg: list):
    print("List variant with argument:", arg)
 
 
@dispatch(object)
def function(arg: object):
    print("Original function with argument", arg, "that has type", type(arg))
 
 
function(42)
function("foo")
function(["foo", "bar", "baz"])
function(1.4142)
function(None)

Statická typová kontrola v tomto případě (a to zcela podle očekávání) vypíše, že typové informace chybí:

$ uv run mypy --strict multiple_dispatch_1.py
 
multiple_dispatch_1.py:1: error: Cannot find implementation or library stub for module named "multipledispatch"  [import-not-found]
multiple_dispatch_1.py:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
multiple_dispatch_1.py:8: error: Name "function" already defined on line 3  [no-redef]
multiple_dispatch_1.py:13: error: Name "function" already defined on line 3  [no-redef]
multiple_dispatch_1.py:14: error: Missing type parameters for generic type "list"  [type-arg]
multiple_dispatch_1.py:18: error: Name "function" already defined on line 3  [no-redef]
Found 5 errors in 1 file (checked 1 source file)

Vícenásobná definice té samé funkce je při statické typové kontrole nalezena i v dalším demonstračním příkladu:

from multipledispatch import dispatch
 
@dispatch(int)
def function(arg: int):
    print("Integer variant with argument:", arg)
 
 
@dispatch(int, int)
def function(arg1: int, arg2: int):
    print("Integer variant with two arguments:", arg1, arg2)
 
 
@dispatch(str)
def function(arg: str):
    print("String variant with argument:", arg)
 
 
@dispatch(str, int)
def function(arg1: str, arg2: int):
    print("String+int variant with arguments:", arg1, arg2)
 
 
@dispatch(list)
def function(arg: list):
    print("List variant with argument:", arg)
 
 
@dispatch(object)
def function(arg: object):
    print("Original function with argument", arg, "that has type", type(arg))
 
 
function(42)
function(42, 0)
function("foo")
function("foo", 42)
function(["foo", "bar", "baz"])
function(1.4142)
function(None)

Výsledky statické typové kontroly budou v tomto případě vypadat následovně:

$ uv run mypy --strict multiple_dispatch_2.py
 
multiple_dispatch_2.py:1: error: Cannot find implementation or library stub for module named "multipledispatch"  [import-not-found]
multiple_dispatch_2.py:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
multiple_dispatch_2.py:8: error: Name "function" already defined on line 3  [no-redef]
multiple_dispatch_2.py:13: error: Name "function" already defined on line 3  [no-redef]
multiple_dispatch_2.py:18: error: Name "function" already defined on line 3  [no-redef]
multiple_dispatch_2.py:23: error: Name "function" already defined on line 3  [no-redef]
multiple_dispatch_2.py:24: error: Missing type parameters for generic type "list"  [type-arg]
multiple_dispatch_2.py:28: error: Name "function" already defined on line 3  [no-redef]
Found 7 errors in 1 file (checked 1 source file)

A konečně poslední případ s trojnásobným dispatchem:

AI skoleni

from multipledispatch import dispatch
 
@dispatch(int, int, int)
def function(arg1: int, arg2: int, arg3: int):
    print("Variant [int, int, int]")
 
@dispatch(str, int, int)
def function(arg1: str, arg2: int, arg3: int):
    print("Variant [str, int, int]")
 
@dispatch(int, str, int)
def function(arg1: int, arg2: str, arg3: int):
    print("Variant [int, str, int]")
 
@dispatch(int, int, str)
def function(arg1: int, arg2: int, arg3: str):
    print("Variant [int, int, str]")

Výsledky statické typové kontroly:

$ uv run mypy --strict multiple_dispatch_3.py
 
multiple_dispatch_3.py:1: error: Cannot find implementation or library stub for module named "multipledispatch"  [import-not-found]
multiple_dispatch_3.py:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
multiple_dispatch_3.py:7: error: Name "function" already defined on line 3  [no-redef]
multiple_dispatch_3.py:11: error: Name "function" already defined on line 3  [no-redef]
multiple_dispatch_3.py:15: error: Name "function" already defined on line 3  [no-redef]
Found 4 errors in 1 file (checked 1 source file)

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 některé dnešní příklady i výše zmíněnou knihovnu multipledispatch):

# 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
       
182 frequencies.py získání četnosti prvků v sekvenci https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/frequencies.py
183 interpose_infinite.py operace interpose a nekonečná sekvence na vstupu https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/in­terpose_infinite.py
184 isdistinct.py test, zda sekvence obsahuje unikátní prvky https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/isdistinct.py
185 partitionby1.py rozdělení prvků sekvence na základě výsledků funkce pro každý prvek https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/partitionby1.py
186 partitionby2.py dtto, ale s odlišnou funkcí a vstupem https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/partitionby2.py
187 partitionby_infinite.py rozdělení prvků nekonečné sekvence https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/par­titionby_infinite.py
188 partitionby_infinite2.py rozdělení prvků nekonečné sekvence https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/par­titionby_infinite2.py
189 sliding_window1.py posuvné okno nad sekvencí https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/sli­ding_window1.py
190 sliding_window2.py dtto, ale pro odlišné parametry https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/sli­ding_window2.py
191 sliding_window_infinite.py posuvné okno a nekonečná vstupní sekvence https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/sli­ding_window_infinite.py
192 unique1.py nalezení unikátních prvků v sekvenci https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/unique1.py
193 unique2.py dtto, ale pro odlišné parametry https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/unique2.py
194 partition_all.py operace partition_all https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/par­tition_all.py
195 get.py operace get https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/get.py
196 pluck.py operace pluck https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/pluck.py
197 join1.py operace join, základní způsob použití https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/join1.py
198 join2.py operace join, výběr ze spojených prvků https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/join2.py
199 join3.py operace inner join https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/join3.py
200 join4.py operace outer join https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/join4.py
201 join5.py operace outer join https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/join5.py
       
202 curry1.py curryfikace funkce se dvěma parametry https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/curry1.py
203 curry2.py curryfikace funkce se třemi parametry https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/curry2.py
204 curry3.py curryfikace realizovaná formou dekorátoru https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/curry3.py
205 curry4.py curryfikace realizovaná formou dekorátoru https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/curry4.py
206 curry_no_params.py curryfikace funkce bez parametrů https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/cu­rry_no_params.py
207 curry_one_param.py curryfikace funkce s jediným parametrem https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/cu­rry_one_param.py
208 curried_no_params.py curryfikace funkce bez parametrů realizovaná formou dekorátoru https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/cu­rried_no_params.py
209 curried_one_param.py curryfikace funkce s jedním parametrem realizovaná formou dekorátoru https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/cu­rried_one_param.py
       
210 head1.py operace typu head realizovaná explicitním kódem https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/head1.py
211 head2.py operace typu head realizovaná uživatelskou funkcí https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/head2.py
212 head3.py operace typu head realizovaná curryfikací https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/head3.py
213 head4.py operace typu head založená na již curryfikované funkci take https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/head4.py
       
214 compose1.py kompozice funkcí zprava doleva, příklad číslo 1 https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/compose1.py
215 compose2.py kompozice funkcí zprava doleva, příklad číslo 2 https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/compose2.py
216 compose3.py kompozice funkcí zprava doleva, příklad číslo 3 https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/compose3.py
217 compose4.py kompozice funkcí zprava doleva, využití anonymních funkcí https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/compose4.py
218 compose_left1.py kompozice funkcí zleva doprava, příklad číslo 1 https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/com­pose_left1.py
219 compose_left2.py kompozice funkcí zleva doprava, příklad číslo 2 https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/com­pose_left2.py
220 compose_left3.py kompozice funkcí zleva doprava, příklad číslo 3 https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/com­pose_left3.py
221 compose_left4.py kompozice funkcí zleva doprava, využití anonymních funkcí https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/com­pose_left4.py
222 pipe1.py vytvoření kolony funkcí, příklad číslo 1 https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/pipe1.py
223 pipe2.py vytvoření kolony funkcí, příklad číslo 2 https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/pipe2.py
224 pipe3.py vytvoření kolony funkcí, příklad číslo 3 https://github.com/tisnik/most-popular-python-libs/blob/master/toolz/pipe3.py
       
225 single_dispatch0.py zobrazení nápovědy k dekorátoru @singledispatch https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/single_dispatch0.py
226 single_dispatch1.py základní aplikace dekorátoru @singledispatch https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/single_dispatch1.py
227 single_dispatch2.py základní aplikace dekorátoru @singledispatch, odlišné jméno funkce https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/single_dispatch2.py
228 single_dispatch3.py rozpoznání parametru typu NoneType https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/single_dispatch3.py
229 single_dispatch4.py varianty funkcí s plnými typovými informacemi (nekorektní deklarace seznamu) https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/single_dispatch4.py
230 single_dispatch5.py varianty funkcí s plnými typovými informacemi (korektní deklarace seznamu) https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/single_dispatch5.py
231 single_dispatch6.py dekorátor @singledispatch a funkce se dvěma argumenty https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/single_dispatch6.py
232 single_dispatch7.py složitější deklarace typů a dekorátor @singledispatch https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/single_dispatch7.py
233 single_dispatch8.py způsob překladu funkce s dynamickým výběrem variant do bajtkódu Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/single_dispatch8.py
       
232 single_dispatch_method0.py zobrazení nápovědy k dekorátoru @singledispatchmethod https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/single_dispatch_method.py
233 single_dispatch_method1.py základní použití dekorátoru @singledispatchmethod https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/single_dispatch_method.py
234 single_dispatch_method2.py kombinace dekorátorů @singledispatchmethod a @staticmethod https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/single_dispatch_method.py
235 single_dispatch_method3.py kombinace dekorátorů @singledispatchmethod a @staticmethod https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/single_dispatch_method.py
236 single_dispatch_method4.py složitější využití dekorátoru @singledispatchmethod https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/single_dispatch_method.py
237 single_dispatch_method5.py složitější využití dekorátoru @singledispatchmethod https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/single_dispatch_method.py
       
238 multiple_dispatch0.py zobrazení nápovědy k dekorátoru @dispatch (ve skutečnosti multiple dispatch) https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/multiple_dispatch0.py
239 multiple_dispatch1.py dekorátor @dispatch založený na dynamickém výběru na základě jednoho parametru https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/multiple_dispatch1.py
240 multiple_dispatch2.py dekorátor @dispatch založený na dynamickém výběru na základě až dvou parametrů https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/multiple_dispatch2.py
241 multiple_dispatch3.py dekorátor @dispatch založený na dynamickém výběru na základě tří parametrů https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/multiple_dispatch3.py

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. Curry v knihovně Toolz
    https://toolz.readthedocs­.io/en/latest/curry.html
  60. Compose v knihovně Toolz
    https://toolz.readthedocs­.io/en/latest/api.html#to­olz.functoolz.compose
  61. Pipe v knihovně Toolz
    ihttps://toolz.readthedoc­s.io/en/latest/api.html#to­olz.functoolz.pipe
  62. Toolz (PyToolz) na GitHubu
    https://github.com/pytoolz/toolz
  63. Fn.py: enjoy FP in Python
    https://github.com/kachayev/fn.py
  64. Funcy na PyPi
    https://pypi.org/project/funcy/
  65. 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/
  66. Funkce vyššího řádu v knihovně Underscore
    https://www.root.cz/clanky/funkce-vyssiho-radu-v-knihovne-underscore/
  67. Awesome functional Python
    https://github.com/sfermigier/awesome-functional-python
  68. lispy
    https://pypi.org/project/lispy/
  69. clojure_py na indexu PyPi
    https://pypi.python.org/py­pi/clojure_py
  70. PyClojure
    https://github.com/eigenhom­bre/PyClojure
  71. Hy na GitHubu
    https://github.com/hylang/hy
  72. Hy: The survival guide
    https://notes.pault.ag/hy-survival-guide/
  73. Hy běžící na monitoru terminálu společnosti Symbolics
    http://try-hy.appspot.com/
  74. Welcome to Hy’s documentation!
    http://docs.hylang.org/en/stable/
  75. Hy na PyPi
    https://pypi.org/project/hy/#des­cription
  76. Getting Hy on Python
    https://lwn.net/Articles/596626/
  77. Dynamický výběr
    https://cs.wikipedia.org/wi­ki/Dynamick%C3%BD_v%C3%BDb%C4%9Br
  78. Dynamic dispatch
    https://en.wikipedia.org/wi­ki/Dynamic_dispatch#Single_an­d_multiple_dispatch
  79. Double dispatch
    https://en.wikipedia.org/wi­ki/Double_dispatch
  80. Multiple dispatch
    https://en.wikipedia.org/wi­ki/Multiple_dispatch
  81. How Python’s Multiple Dispatch Works
    https://medium.com/@Alexan­derObregon/how-pythons-multiple-dispatch-works-8c69e24c45a6
  82. multipledispatch na PyPi
    https://pypi.org/project/mul­tipledispatch/
  83. Lesson: Annotations
    https://docs.oracle.com/ja­vase/tutorial/java/annota­tions/
  84. Annotations in Java
    https://www.geeksforgeeks­.org/java/annotations-in-java/
  85. multipledispatch na GitHubu
    https://github.com/mrocklin/mul­tipledispatch/
  86. Five-minute Multimethods in Python
    https://www.artima.com/we­blogs/viewpost.jsp?thread=101605
  87. Protocols (Clojure)
    https://clojure.org/referen­ce/protocols
  88. Julia language: methods
    https://docs.julialang.or­g/en/v1/manual/methods/#Met­hods
  89. Plum: Multiple Dispatch in Python
    https://pypi.org/project/plum-dispatch/
  90. multimethod
    https://pypi.org/project/multimethod/
  91. multimethod-dispatcher
    https://pypi.org/project/multimethod-dispatcher/
  92. multipledispatch
    https://pypi.org/project/mul­tipledispatch/
  93. Seriál Programovací jazyk Julia
    https://www.root.cz/seria­ly/programovaci-jazyk-julia/
  94. The Zen of Polymorphism: Choosing between isinstance(), methods, and @singledispatch
    https://pyvideo.org/pycon-us-2025/the-zen-of-polymorphism-choosing-between-isinstance-methods-and-singledispatch.html
  95. The Zen of Polymorphism: Choosing between isinstance(), methods, and @singledispatch – Brett Slatkin (Youtube)
    https://www.youtube.com/wat­ch?v=hidy15rK2a4
Neutrální ikona do widgetu na odběr článků ze seriálů

Zajímá vás toto téma? Chcete se o něm dozvědět víc?

Objednejte si upozornění na nově vydané články do vašeho mailu. Žádný článek vám tak neuteče.


Autor článku

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



Nejnovější články