2.37. Adlandırılmış demetler (named tuple) ve deque’ler

Listeler, demetler (tuple), sözlükler ve kümeler çoğu veri ihtiyacını karşılar. collections modülündeki diğer üç kapsayıcı, yerleşiklerin hantal biçimde ele aldığı belirli sorunlara uyar.

2.37.1. namedtuple – sınıf olmadan tipli kayıtlar

Düz bir demet (tuple) değerleri konuma göre saklar. Bu, küçük, kısa ömürlü bir 2’li veya 3’lü demet için sorun değildir, ancak bunun ötesinde point[0] ve point[1] ne tuttukları konusunda yanıltmaya başlar. collections.namedtuple(), alanları adlandırılmış yeni bir demet alt sınıfı döndürür:

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

Alanlar argümanı, ad dizelerinden oluşan bir dizidir (veya CPython’da boşlukla ayrılmış tek bir dize; MicroPython daha katıdır – bir demet veya liste geçirin).

Bir sınıf yerine neden namedtuple kullanmalı?

  • O bir demettir (tuple). Yineleme, ayrıştırma (unpacking), eşitlik, karma (hashing) ve sözlük anahtarı olarak kullanımın tümü bedelsiz çalışır.

  • Değişmezdir (immutable). r.temp = ... ataması AttributeError yükseltir; bu, tam olarak bir kayıt türü için istediğiniz şeydir.

  • Aynı alanlara sahip bir sınıf örneğinden daha az RAM tüketir – demetin depolaması bitişiktir, __dict__ yoktur.

Eşdeğer sınıfla karşılaştırıldığında, bir namedtuple bildirimi tek satırdır. Ödün, alanların salt okunur olmasıdır – bir okumayı “değiştirmek” için yenisini oluşturursunuz.

2.37.2. deque – sınırlı bir halka arabelleği (ring buffer)

Bir liste sonda (append / pop) hızlıdır ve başta yavaştır (insert(0, ...) / pop(0) her diğer öğeyi kaydırır). Bir collections.deque her iki uçta da hızlıdır – baş ve kuyruk işaretçileriyle indekslenen bir halka arabelleğidir, bu nedenle her iki taraftaki append ve pop, deque kaç öğe tutarsa tutsun aynı sabit miktarda işle çalışır.

MicroPython’da yapı (construction), bu sırada hem bir başlangıç yinelenebiliri (iterable) hem de bir maksimum uzunluk gerektirir:

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

Sınırlı bir deque dolu olduğunda, her append en eski öğeyi düşürür. Bu, deque’i “son N örnek”, “son N günlük satırı” veya sonsuza kadar büyümesi gerekmeyen herhangi bir kayan pencere için ideal kılar.

MicroPython’un deque’inde sunulan yöntemler bilinçli olarak en aza indirilmiştir:

  • append(x) – sağa ekler.

  • appendleft(x) – sola ekler.

  • extend(iterable) – yinelenebilirdeki her öğeyi ekler.

  • pop() – sağ ucu kaldırır ve döndürür. Boşken IndexError yükseltir.

  • popleft() – sol ucu kaldırır ve döndürür.

CPython’un deque’inden dikkate değer eksiklikler: clear, count, index, remove, reverse, rotate, maxlen özniteliği veya __contains__ yok. Yineleme ve alt simge (subscript) indeksleme çalışır:

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

Tipik bir kullanım: eğilim değişikliklerini saptamak için son birkaç sensör okumasını tutmak:

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 – sıra eşitliğin bir parçası olduğunda

Sıradan dict, MicroPython 1.13 ve CPython 3.7’den bu yana ekleme sırasını korur. Bu, insanların eskiden collections.OrderedDict‘e başvurmasının en yaygın nedenini kapsar.

OrderedDict‘in düz bir sözlüğün vermediği, hâlâ size sunduğu şey:

  • OrderedDict eşitliği sırayı dikkate alır. İki sıradan sözlük, ekleme sırasından bağımsız olarak aynı anahtar/değer çiftlerine sahip oldukları her durumda eşit karşılaştırılır. İki OrderedDict örneği yalnızca çiftleri aynı sıradaysa eşittir:

    >>> 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, yapılandırmayı anahtar sırasını önemseyen bir biçime (TOML, bazı YAML tüketicileri) serileştirirken veya kodunuzun okuyucularına sıranın önemli olduğuna dair açık bir belge ipucu vermek istediğinizde kullanışlıdır.

Günlük kod için yerleşik dict‘i tercih edin. OrderedDict‘e yalnızca sıra-eşitliğin-bir-parçasıdır anlamı veya belgesel değeri gerçekten bir şey kazandırdığında başvurun.

Üç kapsayıcının her biri dar bir uyuma sahiptir. Adlandırılmış demetler, elle yazılmış kayıt sınıflarının yerini alır; deque’ler, sınırlı kuyruklar için listelerin yerini alır; sıralı sözlükler ise ekleme sırasını sözleşmenin bir parçası yapar.