Lekce 9 - ChainMap, NamedTuple a DeQue v Pythonu
V minulé lekci, Komprehence, lambda výrazy a funkce v Pythonu, jsme si ukázali seznamové komprehence, lambda výrazy a některé vestavěné funkce pro práci s iterovatelnými objekty.
V tomto tutoriálu kolekcí v Pythonu se budeme věnovat
třem jejich zástupcům. Konkrétně se zaměříme na třídy
ChainMap, NamedTuple a Deque z modulu
collections.
ChainMap
ChainMap je datový typ, který nám umožňuje
sdružovat více slovníků do jednoho logického celku. Jinými slovy
nám ChainMap umožňuje jednoduše a efektivně pracovat s
více slovníky jako s jedním.
ChainMap se často používá v případě, když chceme hledat
hodnotu pro klíč ve více slovnících. Velkou výhodou
ChainMap je, že nám umožňuje udržovat všechny slovníky v
jednom objektu. Hledání ve sdružených slovnících bude
probíhat postupně v pořadí, v jakém byly uvedeny při vytvoření instance,
dokud se pro klíč nenajde odpovídající hodnota.
Příklad použití
ChainMap
Použití ChainMap v Pythonu je velmi jednoduché. Prvním
krokem je importovat modul collections. Dále si nadefinujeme
slovníky slovnik1 a slovnik2 a poté vytvoříme
proměnnou mapa, která bude obsahovat instanci třídy
ChainMap:
from collections import ChainMap slovnik1 = {'a':1, 'b':2} slovnik2 = {'c':3, 'b':4} mapa = ChainMap(slovnik1, slovnik2)
Následně si vypíšeme obsah proměnné mapa a na dalším
řádku výpis zopakujeme pro index ['b']:
print(mapa) print(mapa['b'])
Výstupem v konzoli bude:
Konzolová aplikace
ChainMap({'a': 1, 'b': 2}, {'c': 3, 'b': 4})
2
Vidíme, že proměnná mapa se chová jako slovník, ve kterém
jsou uloženy hodnoty ze slovnik1 a slovnik2.
Následný výpis print(mapa['b']) vrací hodnotu klíče
b z prvního slovníku, ve kterém je k dispozici, tj. ze
slovnik1.
Nyní si vyzkoušíme obsah proměnné mapa modifikovat.
Přidáme řádek s kódem mapa['c'] = 5. Standardně změny
probíhají nad prvním slovníkem v kolekci, takže tím
přidáme do proměnné mapa nový klíč c s hodnotou
5, stejně jako do slovníku slovnik1:
mapa['c'] = 5 print(mapa)
V konzoli tedy uvidíme:
Konzolová aplikace
ChainMap({'a': 1, 'b': 2, 'c': 5}, {'c': 3, 'b': 4})
Teď modifikujeme jeden ze slovníků a opět si vypíšeme obsah proměnné
mapa:
slovnik2['c'] = 6 print(mapa)
Výstup v konzoli bude:
Konzolová aplikace
ChainMap({'a': 1, 'b': 2, 'c': 5}, {'c': 6, 'b': 4})
Vidíme, že hodnota klíče c se v proměnné mapa
(v druhé části) změnila na 6, protože se na 6
změnila i v podkladovém slovníku (slovnik2['c'] = 6). Nicméně
hodnota mapa['c'] by zůstala 5, protože bude dříve
nalezena v prvním slovníku. To bude platit, dokud tuto hodnotu nesmažeme:
del mapa['c'] print(mapa) print(slovnik1) print(mapa['c'])
Výstup v konzoli bude:
Konzolová aplikace
ChainMap({'a': 1, 'b': 2}, {'c': 6, 'b': 4})
{'a': 1, 'b': 2}
6
Metody pro práci s
ChainMap
Třída ChainMap obsahuje mimo jiné následující metody:
maps- vrátí novou instanceChainMap, která přidá zadaný slovník (nebo slovníky) na konec seznamu slovníků,new_child()- přidá nový slovník na první pozici v seznamu,get(key[, default])- vrátí hodnotu pro daný klíč. Pokud hodnota není nalezena, vrátí hodnotu default (pokud je zadána), jinak vyvolá výjimkuKeyError,keys()- vrátí seznam všech klíčů,values()- vrátí seznam všech hodnot,items()- vrátí seznam všech položek ve formátu (klíč, hodnota).
Výše uvedené si tedy shrneme. Platí, že ChainMap je
aktualizovatelný pohled nad více slovníky. Hodnoty v
příslušné instanci se mění v závislosti na změnách v
jednotlivých podkladových slovnících.
NamedTuple
Třída NamedTuple je speciální případ neseřazeného
datového typu, který kombinuje výhody tuple a slovníku. Stejně jako tuple
má také pevnou délku a její instance nelze modifikovat. Zásadní rozdíl
ale spočívá v tom, že jednotlivé položky mohou být přístupné pomocí
jména (stejně jako v případě slovníku).
Výhodou NamedTuple tedy je, že umožňuje jasnější a
čitelnější kód, protože jména položek jsou přímo součástí kódu.
Díky pevné délce je také efektivnější než použití slovníku.
Příklad použití
NamedTuple
NamedTuple se vytváří pomocí funkce
namedtuple(). Nejprve si třídu NamedTuple
naimportujeme z modulu collections. Poté pomocí funkce
namedtuple() vytvoříme třídu Osoba, která
rozšiřuje NamedTuple o položky jmeno,
prijmeni a vek. Následně vytvoříme proměnnou
student, v níž bude instance třídy Osoba:
from collections import namedtuple Osoba = namedtuple("Osoba", ["jmeno", "prijmeni", "vek"]) student = Osoba("Jan", "Novák", 26)
K položkám NamedTuple pak budeme přistupovat pomocí jména
položky jako atributu instance, jako by šlo o obyčejné atributy třídy:
print("Jméno a příjmení studenta: "+ student.jmeno + " " + student.prijmeni) print("Věk studenta:", student.vek)
V konzoli vidíme výstup:
Konzolová aplikace
Jméno a příjmení studenta: Jan Novák
Věk studenta: 26
Následujícím způsobem pak vypíšeme celou instanci
NamedTuple z proměnné turista:
from collections import namedtuple Turista = namedtuple('Turista', ['jmeno', 'vek', 'zeme']) turista = Turista('Jan', 26, 'Norsko') print(turista)
Výstupem v konzoli bude:
Konzolová aplikace
Turista(jmeno='Jan', vek=26, zeme='Norsko')
Metody pro práci s
NamedTuple
Třída NamedTuple obsahuje mimo jiné následující
metody:
make()- umožňuje vytvořit instanciNamedTuplez iterovatelných objektů jako jsou seznamy nebo sekvence,asdict()- slouží k převodu na slovník,replace()- vytvoří novou instanciNamedTuplese stejným názvem, ale s novými hodnotami. Původní instanceNamedTuplezůstává nezměněná,fields- slouží k získání seznamu názvů všech položek v instanciNamedTuple.
V praxi se NamedTuple často používá jako výkonný a
jednoduchý způsob, jak organizovat a ukládat data, která spojuje nějaký
kontext, ale nejsou k nim třeba žádné další metody nebo funkce.
DeQue
Třída Deque (zkratka pro "Double-Ended Queue") představuje
specifický typ fronty, který je implementovaný jako dvoustranně otevřený
seznam. To umožňuje efektivně přidávat a odebírat prvky z obou stran. V
praxi se DeQue využívá například při řešení úloh s
BFS (Breadth-First Search) a DFS (Depth-First Search),
což jsou dva typy algoritmů pro hledání nejkratší cesty, hledání všech
cest, hledání komponent grafu apod.
Příklad použití DeQue
Použití DeQue v Pythonu je velmi jednoduché. Prvním naším
krokem bude importovat modul collections. Poté vytvoříme
instanci třídy DeQue a vypíšeme si ji:
from collections import deque deq = deque([1,2,3,4]) print(deq)
Výstupem v konzoli bude:
Konzolová aplikace
deque([1, 2, 3, 4])
Vyzkoušejme si teď, jak funguje naše tvrzení o otevřených koncích
seznamu. Využijeme k tomu metody append(),
appendleft(), pop() a popleft():
deq.append(5) print(deq) deq.appendleft(0) print(deq) deq.pop() print(deq) deq.popleft() print(deq)
V konzoli vidíme výsledek:
Konzolová aplikace
deque([1, 2, 3, 4])
deque([1, 2, 3, 4, 5])
deque([0, 1, 2, 3, 4, 5])
deque([0, 1, 2, 3, 4])
deque([1, 2, 3, 4])
Podívejme se teď blíže na to, co kód vykonal:
- nejprve jsme vytvořili frontu
deqs prvky1,2,3a4, - pomocí metody
append()jsme přidali prvek5na konec fronty, - pomocí metody
appendleft()jsme přidali prvek0na začátek fronty, - pomocí metody
pop()jsme odebrali poslední prvek z fronty, - pomocí metody
popleft()jsme odebrali první prvek z fronty.
Metody pro práci s DeQue
Třída DeQue obsahuje kromě už uvedených také
následující často využívané metody:
clear()- smaže všechny prvky,count()- vrátí počet výskytů určitého prvku,extend()- přidá více prvků na konec,extendleft()- přidá více prvků na začátek,remove()- odstraní prvek s určitou hodnotou,reverse()- otočí pořadí prvků.
Výhodou DeQue oproti prostému seznamu je rychlost, protože
přidávání a odebírání prvků z obou stran je v ní implementováno
efektivně. Často se používá jako zásobník nebo fronta, do které lze
prvky na jednu stranu přidávat a z druhé strany je odebírat.
To by bylo pro tuto lekci vše.
V následujícím kvízu, Kvíz - Komprehence, Lambda, Chainmap a DeQue v Pythonu, si vyzkoušíme nabyté zkušenosti z předchozích lekcí.

