2.37. Pojmenované n-tice a deque¶
Seznamy, n-tice, slovníky a množiny pokrývají většinu datových potřeb. Tři další kontejnery v modulu collections se hodí na specifické problémy, které vestavěné typy zvládají neobratně.
2.37.1. namedtuple – typované záznamy bez třídy¶
Obyčejná n-tice ukládá hodnoty podle pozice. To je v pořádku pro malou, krátce žijící 2- nebo 3-tici, ale dále už point[0] a point[1] začínají zastírat, co obsahují. collections.namedtuple() vrací novou podtřídu n-tice, jejíž pole mají jména:
>>> from collections import namedtuple
>>> Reading = namedtuple('Reading', ('temp', 'humidity', 'ts'))
>>> r = Reading(22.5, 41.0, 137204)
>>> r.temp
22.5
>>> r.humidity
41.0
>>> r[0]
22.5
Argument fields je sekvence řetězců s názvy (nebo v CPythonu jeden řetězec oddělený mezerami; MicroPython je přísnější – předejte n-tici nebo seznam).
Proč použít namedtuple namísto třídy?
Je to n-tice. Iterace, rozbalení, rovnost, hashování a použití jako klíč slovníku fungují zdarma.
Je neměnná. Přiřazení
r.temp = ...vyvoláAttributeError, což je přesně to, co u typu záznamu chcete.Stojí méně RAM než instance třídy se stejnými poli – úložiště n-tice je souvislé, bez
__dict__.
Ve srovnání s ekvivalentní třídou je deklarace namedtuple jeden řádek. Kompromisem je, že pole jsou pouze pro čtení – abyste „změnili“ hodnotu, vytvoříte novou.
2.37.2. deque – ohraničený kruhový buffer¶
Seznam je rychlý na konci (append / pop) a pomalý na začátku (insert(0, ...) / pop(0) oba posunou každý další prvek). collections.deque je rychlá na obou koncích – je to kruhový buffer indexovaný ukazateli na hlavu a ocas, takže append a pop na kterékoli straně proběhnou se stejným pevným množstvím práce bez ohledu na to, kolik položek deque obsahuje.
Konstrukce v MicroPythonu vyžaduje jak počáteční iterovatelný objekt, tak maximální délku, v tomto pořadí:
>>> from collections import deque
>>> events = deque((), 5)
>>> for i in range(8):
... events.append(i)
>>> list(events)
[3, 4, 5, 6, 7]
Když je ohraničená deque plná, každý append zahodí nejstarší položku. To činí z deque ideální volbu pro „posledních N vzorků“, „posledních N řádků logu“ nebo libovolné klouzavé okno, které nemusí růst donekonečna.
Metody vystavené na deque v MicroPythonu jsou záměrně minimální:
append(x)– přidá doprava.appendleft(x)– přidá doleva.extend(iterable)– připojí každou položku z iterovatelného objektu.pop()– odebere a vrátí pravý konec. Na prázdné vyvoláIndexError.popleft()– odebere a vrátí levý konec.
Pozoruhodné nedostatky oproti deque z CPythonu: žádné clear, count, index, remove, reverse, rotate, atribut maxlen ani __contains__. Iterace a indexování přes index fungují:
>>> events[0]
3
>>> for e in events:
... print(e)
Typické použití: udržování posledních několika hodnot senzoru pro detekci změn trendu:
history = deque((), 10)
def push(reading):
history.append(reading)
if len(history) == 10 and history[-1] > 2 * history[0]:
print('reading is climbing')
2.37.3. OrderedDict – když je pořadí součástí rovnosti¶
Běžný dict zachovává pořadí vkládání od MicroPythonu 1.13 a CPythonu 3.7. To pokrývá nejčastější důvod, proč lidé dříve sahali po collections.OrderedDict.
Co vám OrderedDict stále poskytuje oproti obyčejnému slovníku:
Rovnost
OrderedDictbere v úvahu pořadí. Dva běžné slovníky se porovnají jako rovné, kdykoli mají stejné dvojice klíč/hodnota, bez ohledu na pořadí vkládání. Dvě instanceOrderedDictjsou rovné pouze tehdy, jsou-li jejich dvojice ve stejném pořadí:>>> from collections import OrderedDict >>> OrderedDict([('a', 1), ('b', 2)]) == OrderedDict([('b', 2), ('a', 1)]) False >>> {'a': 1, 'b': 2} == {'b': 2, 'a': 1} True
OrderedDictje užitečný, když serializujete konfiguraci do formátu, kterému záleží na pořadí klíčů (TOML, někteří konzumenti YAML), nebo když chcete čtenářům svého kódu jasně dokumentačně naznačit, že na pořadí záleží.
Pro běžný kód dejte přednost vestavěnému dict. Po OrderedDict sáhněte jen tehdy, když sémantika „pořadí je součástí rovnosti“ nebo dokumentační hodnota skutečně něco přinese.
Každý z těchto tří kontejnerů má jedno úzké uplatnění. Pojmenované n-tice nahrazují ručně psané třídy záznamů; deque nahrazují seznamy pro ohraničené fronty; uspořádané slovníky činí pořadí vkládání součástí kontraktu.