2.37. Named tuple dan deque

List, tuple, dictionary, dan set mencakup sebagian besar kebutuhan data. Tiga kontainer lain dalam modul collections cocok untuk masalah spesifik yang ditangani secara canggung oleh tipe bawaan.

2.37.1. namedtuple -- record bertype tanpa kelas

Tuple biasa menyimpan nilai berdasarkan posisi. Itu baik-baik saja untuk tuple 2 atau 3 yang kecil dan berumur pendek, tetapi setelah itu point[0] dan point[1] mulai menyembunyikan apa yang mereka simpan. collections.namedtuple() mengembalikan subkelas tuple baru yang field-nya memiliki nama:

>>> 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

Argumen fields adalah urutan string nama (atau satu string yang dipisahkan spasi putih di CPython; MicroPython lebih ketat -- berikan tuple atau list).

Mengapa menggunakan namedtuple alih-alih kelas?

  • Ini adalah tuple. Iterasi, unpacking, kesamaan, hashing, dan penggunaan sebagai kunci dict semuanya bekerja secara gratis.

  • Ini bersifat immutable. Menetapkan ulang r.temp = ... memunculkan AttributeError, yang persis seperti yang Anda inginkan untuk tipe record.

  • Biaya RAM-nya lebih sedikit dari instance kelas dengan field yang sama -- penyimpanan tuple bersifat kontinu, tanpa __dict__.

Dibandingkan dengan kelas yang setara, deklarasi namedtuple hanya satu baris. Trade-off-nya adalah field bersifat read-only -- untuk "mengubah" pembacaan, Anda membuat yang baru.

2.37.2. deque -- ring buffer terbatas

List cepat di bagian akhir (append / pop) dan lambat di bagian awal (insert(0, ...) / pop(0) keduanya menggeser setiap elemen lain). collections.deque cepat di kedua ujungnya -- ini adalah ring buffer yang diindeks oleh pointer head dan tail, sehingga append dan pop di kedua sisi berjalan dalam jumlah pekerjaan yang sama dan tetap terlepas dari berapa banyak item yang dipegang deque.

Konstruksi di MicroPython memerlukan baik iterable awal maupun panjang maksimum, dalam urutan tersebut:

>>> from collections import deque
>>> events = deque((), 5)
>>> for i in range(8):
...     events.append(i)
>>> list(events)
[3, 4, 5, 6, 7]

Ketika deque terbatas penuh, setiap append menghapus item tertua. Hal ini membuat deque ideal untuk "N sampel terakhir", "N baris log terakhir", atau jendela bergulir mana pun yang tidak perlu tumbuh selamanya.

Metode yang tersedia di deque MicroPython sengaja dibuat minimal:

  • append(x) -- tambahkan ke kanan.

  • appendleft(x) -- tambahkan ke kiri.

  • extend(iterable) -- tambahkan setiap item dari iterable.

  • pop() -- hapus dan kembalikan ujung kanan. Memunculkan IndexError jika kosong.

  • popleft() -- hapus dan kembalikan ujung kiri.

Penghilangan yang perlu diperhatikan dari deque CPython: tidak ada clear, count, index, remove, reverse, rotate, atribut maxlen, atau __contains__. Iterasi dan pengindeksan subskrip bekerja:

>>> events[0]
3
>>> for e in events:
...     print(e)

Penggunaan tipikal: menyimpan beberapa pembacaan sensor terakhir untuk mendeteksi perubahan tren:

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 -- ketika urutan adalah bagian dari kesamaan

Kelas dict biasa telah mempertahankan urutan penyisipan sejak MicroPython 1.13 dan CPython 3.7. Itu mencakup alasan paling umum mengapa orang biasanya menggunakan collections.OrderedDict.

Apa yang OrderedDict masih berikan yang tidak diberikan dict biasa:

  • Kesamaan OrderedDict mempertimbangkan urutan. Dua dict biasa dibandingkan sama kapan pun mereka memiliki pasangan kunci/nilai yang sama, terlepas dari urutan penyisipan. Dua instance OrderedDict sama hanya jika pasangannya dalam urutan yang sama:

    >>> from collections import OrderedDict
    >>> OrderedDict([('a', 1), ('b', 2)]) == OrderedDict([('b', 2), ('a', 1)])
    False
    >>> {'a': 1, 'b': 2} == {'b': 2, 'a': 1}
    True
    
  • OrderedDict berguna ketika Anda men-serialisasi konfigurasi ke format yang memang memperhatikan urutan kunci (TOML, beberapa konsumen YAML), atau ketika Anda ingin petunjuk dokumentasi yang jelas bahwa urutan penting bagi pembaca kode Anda.

Untuk kode sehari-hari, lebih baik gunakan dict bawaan. Gunakan OrderedDict hanya ketika semantik urutan-adalah-bagian-dari-kesamaan atau nilai dokumentasinya benar-benar memberikan manfaat.

Ketiga kontainer masing-masing memiliki satu kesesuaian yang sempit. Named tuple menggantikan kelas record yang dibuat sendiri; deque menggantikan list untuk antrean terbatas; ordered dict menjadikan urutan penyisipan bagian dari kontrak.