2.37. Named tuple-ök és deque-ek¶
A listák, tuple-ök, szótárak és halmazok a legtöbb adatigényt lefedik. A collections modul három további tárolója olyan konkrét problémákra való, amelyeket a beépített típusok ügyetlenül kezelnek.
2.37.1. namedtuple – típusos rekordok osztály nélkül¶
Egy egyszerű tuple pozíció szerint tárolja az értékeket. Ez rendben van egy kicsi, rövid életű 2- vagy 3-elemű tuple esetén, de azon túl a point[0] és a point[1] kezd hazudni arról, mit is tartalmaz. A collections.namedtuple() egy új tuple-alosztályt ad vissza, amelynek mezői névvel rendelkeznek:
>>> 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
A mezők argumentuma névsztringek sorozata (vagy egyetlen, szóközökkel elválasztott sztring CPythonban; a MicroPython szigorúbb – adj át egy tuple-t vagy listát).
Miért használjunk namedtuple típust osztály helyett?
Mert ez egy tuple. Az iteráció, a kicsomagolás, az egyenlőség, a hashelés és a szótárkulcsként való használat mind ingyen működik.
Mert megváltoztathatatlan. Az
r.temp = ...újraértékadásAttributeErrorhibát vált ki, ami pontosan az, amit egy rekordtípusnál szeretnél.Mert kevesebb RAM-ba kerül, mint egy ugyanolyan mezőkkel rendelkező osztálypéldány – a tuple tárolása összefüggő,
__dict__nélkül.
Az egyenértékű osztállyal összehasonlítva egy namedtuple deklaráció egyetlen sor. A kompromisszum az, hogy a mezők csak olvashatók – egy leolvasás „megváltoztatásához” újat hozol létre.
2.37.2. deque – korlátos gyűrűpuffer¶
Egy lista a végén gyors (append / pop), az elején pedig lassú (az insert(0, ...) és a pop(0) is minden további elemet eltol). A collections.deque mindkét végén gyors – ez egy fej- és farokmutatóval indexelt gyűrűpuffer, így bármelyik oldalon az append és a pop azonos, rögzített mennyiségű munkával fut, függetlenül attól, hány elemet tart a deque.
A MicroPythonban a létrehozás egyszerre igényel egy kezdeti iterálhatót és egy maximális hosszt, ebben a sorrendben:
>>> from collections import deque
>>> events = deque((), 5)
>>> for i in range(8):
... events.append(i)
>>> list(events)
[3, 4, 5, 6, 7]
Amikor egy korlátos deque megtelik, minden append eldobja a legrégebbi elemet. Ez teszi a deque-et ideálissá „az utolsó N minta”, „az utolsó N naplósor” vagy bármilyen gördülő ablak esetén, amelynek nem kell örökké nőnie.
A MicroPython deque-én elérhető metódusok szándékosan minimálisak:
append(x)– hozzáadás a jobb oldalhoz.appendleft(x)– hozzáadás a bal oldalhoz.extend(iterable)– az iterálható minden elemének hozzáfűzése.pop()– a jobb vég eltávolítása és visszaadása. Üres deque eseténIndexErrorhibát vált ki.popleft()– a bal vég eltávolítása és visszaadása.
Figyelemre méltó hiányosságok a CPython deque-éhez képest: nincs clear, count, index, remove, reverse, rotate, maxlen attribútum vagy __contains__. Az iteráció és az indexeléses elérés működik:
>>> events[0]
3
>>> for e in events:
... print(e)
Egy tipikus felhasználás: az utolsó néhány érzékelő-leolvasás megtartása a trendváltozások észleléséhez:
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 – amikor a sorrend az egyenlőség része¶
A szokásos dict a MicroPython 1.13 és a CPython 3.7 óta megőrzi a beszúrási sorrendet. Ez lefedi a leggyakoribb okot, amiért az emberek korábban a collections.OrderedDict után nyúltak.
Amit az OrderedDict még mindig nyújt, amit egy egyszerű szótár nem:
Az
OrderedDictegyenlősége figyelembe veszi a sorrendet. Két szokásos szótár egyenlőnek számít, valahányszor ugyanazok a kulcs/érték párjaik, a beszúrási sorrendtől függetlenül. KétOrderedDictpéldány csak akkor egyenlő, ha a párjaik azonos sorrendben vannak:>>> from collections import OrderedDict >>> OrderedDict([('a', 1), ('b', 2)]) == OrderedDict([('b', 2), ('a', 1)]) False >>> {'a': 1, 'b': 2} == {'b': 2, 'a': 1} True
Az
OrderedDictakkor hasznos, amikor olyan formátumba sorosítod a konfigurációt, amely törődik a kulcsok sorrendjével (TOML, egyes YAML-feldolgozók), vagy amikor egyértelmű dokumentációs jelzést szeretnél adni arról, hogy a sorrend számít a kódod olvasói számára.
A hétköznapi kódhoz inkább a beépített dict típust részesítsd előnyben. Az OrderedDict után csak akkor nyúlj, amikor a sorrend-az-egyenlőség-része szemantika vagy a dokumentációs érték tényleg ad valamit.
A három tároló mindegyikének egy-egy szűk felhasználási területe van. A named tuple-ök kiváltják a kézzel írt rekordosztályokat; a deque-ek kiváltják a listákat korlátos sorok esetén; a rendezett szótárak pedig a beszúrási sorrendet a megállapodás részévé teszik.