2.37. Nimetyt monikot ja kaksipäiset jonot¶
Listat, monikot, sanakirjat ja joukot kattavat useimmat datatarpeet. Kolme muuta säiliötä collections -moduulissa sopivat erityisongelmiin, joita sisäänrakennetut käsittelevät kömpelösti.
2.37.1. namedtuple – tyypitetyt tietueet ilman luokkaa¶
Tavallinen monikko tallentaa arvot sijainnin mukaan. Se on ihan hyvä pienelle, lyhytikäiselle 2- tai 3-monikolle, mutta sen jälkeen point[0] ja point[1] alkavat valehdella siitä, mitä ne pitävät sisällään. collections.namedtuple() palauttaa uuden monikon aliluokan, jonka kentillä on nimet:
>>> 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
Kenttäargumentti on nimimerkkijonojen jono (tai yksi välilyönnein eroteltu merkkijono CPythonissa; MicroPython on tiukempi – anna monikko tai lista).
Miksi käyttää namedtuple-tyyppiä luokan sijaan?
Se on monikko. Iterointi, purkaminen, yhtäsuuruus, tiivistäminen ja käyttö sanakirjan avaimena toimivat kaikki ilmaiseksi.
Se on muuttumaton.
r.temp = ...uudelleenmäärittely nostaaAttributeError-poikkeuksen, mikä on juuri sitä mitä tietuetyypiltä haluat.Se vie vähemmän RAM-muistia kuin luokkainstanssi samoilla kentillä – monikon tallennustila on yhtenäinen, ilman
__dict__-rakennetta.
Vastaavaan luokkaan verrattuna namedtuple-määrittely on yksi rivi. Kompromissi on, että kentät ovat vain luettavia – lukeman ”muuttamiseksi” teet uuden.
2.37.2. deque – rajattu rengaspuskuri¶
Lista on nopea lopussa (append / pop) ja hidas alussa (insert(0, ...) / pop(0) molemmat siirtävät jokaista muuta alkiota). collections.deque on nopea molemmissa päissä – se on rengaspuskuri, joka indeksoidaan pää- ja häntäosoittimilla, joten lisäys ja poisto kummalla tahansa puolella vievät saman kiinteän työmäärän riippumatta siitä, montako alkiota deque sisältää.
Rakentaminen MicroPythonissa vaatii sekä alustavan iteroitavan että enimmäispituuden, tässä järjestyksessä:
>>> from collections import deque
>>> events = deque((), 5)
>>> for i in range(8):
... events.append(i)
>>> list(events)
[3, 4, 5, 6, 7]
Kun rajattu deque on täynnä, jokainen append pudottaa vanhimman alkion. Tämä tekee dequesta ihanteellisen ”viimeiselle N näytteelle”, ”viimeiselle N lokiriville” tai mille tahansa liukuvalle ikkunalle, jonka ei tarvitse kasvaa loputtomasti.
MicroPythonin dequen tarjoamat metodit ovat tarkoituksellisesti minimaaliset:
append(x)– lisää oikealle.appendleft(x)– lisää vasemmalle.extend(iterable)– lisää jokainen alkio iteroitavasta.pop()– poista ja palauta oikea pää. NostaaIndexError-poikkeuksen tyhjälle.popleft()– poista ja palauta vasen pää.
Huomattavat poisjätöt CPythonin dequesta: ei clear, count, index, remove, reverse, rotate, maxlen-attribuuttia eikä __contains__. Iterointi ja alaindeksointi toimivat:
>>> events[0]
3
>>> for e in events:
... print(e)
Tyypillinen käyttö: muutaman viimeisen sensorilukeman säilyttäminen trendimuutosten havaitsemiseksi:
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 – kun järjestys on osa yhtäsuuruutta¶
Tavallinen dict on säilyttänyt lisäysjärjestyksen MicroPython 1.13:sta ja CPython 3.7:stä lähtien. Tämä kattaa yleisimmän syyn, jonka vuoksi ihmiset tapasivat tarttua collections.OrderedDict-tyyppiin.
Mitä OrderedDict antaa sinulle edelleen, mitä tavallinen dict ei anna:
OrderedDict-yhtäsuuruus ottaa huomioon järjestyksen. Kaksi tavallista sanakirjaa vertautuvat yhtäsuuriksi aina kun niillä on samat avain/arvo-parit lisäysjärjestyksestä riippumatta. KaksiOrderedDict-instanssia ovat yhtäsuuria vain, jos niiden parit ovat samassa järjestyksessä:>>> from collections import OrderedDict >>> OrderedDict([('a', 1), ('b', 2)]) == OrderedDict([('b', 2), ('a', 1)]) False >>> {'a': 1, 'b': 2} == {'b': 2, 'a': 1} True
OrderedDicton hyödyllinen kun sarjallistat konfiguraatiota formaattiin, joka välittää avainten järjestyksestä (TOML, jotkin YAML-kuluttajat), tai kun haluat selkeän dokumentaatiovihjeen siitä, että järjestyksellä on merkitystä koodisi lukijoille.
Jokapäiväiseen koodiin suosi sisäänrakennettua dict-tyyppiä. Tartu OrderedDict-tyyppiin vain kun järjestys-on-osa-yhtäsuuruutta-semantiikka tai dokumentaarinen arvo tuottaa todella jotain.
Kullakin kolmesta säiliöstä on yksi kapea sovelluskohde. Nimetyt monikot korvaavat itse tehdyt tietueluokat; dequet korvaavat listat rajatuissa jonoissa; järjestetyt sanakirjat tekevät lisäysjärjestyksestä osan sopimusta.