Python __getitem__ ve operatör garip davranışlara neden oluyor


34

Aşağıdaki davranışı açıklayan nedir:

class Foo:
    def __getitem__(self, item):
        print("?")
        return 1

f = Foo()

1 in f  # prints one ? and returns True

5 in f  # prints ? forever until you raise a Keyboard Exception

# Edit: eventually this fails with OverflowError: iter index too large

Yanıtlar:


45

Bir nesnenin bir __contains__uygulaması yoksa in, temelde şu şekilde çalışan bir varsayılana geri döner:

def default__contains__(self, element):
    for thing in self:
        if thing == element:
            return True
    return False

Ve bir nesnenin bir __iter__uygulaması yoksa for, temelde şu şekilde çalışan bir varsayılana geri döner:

def default__iter__(self):
    i = 0
    try:
        while True:
            yield self[i]
            i += 1
    except IndexError:
        pass

Bu varsayılanlar, nesne bir dizi olarak tasarlanmamış olsa bile kullanılır.

Sizin 1 in fve 5 in ftestler için öntanımlı seçenekler kullanıyor inve forgözlenen davranış yol. derhal 1 in fbulur 1, ama __getitem__asla geri gelmez 5, bu yüzden 5 in fsonsuza dek çalışır.

(Aslında, Python'un referans uygulamasında, varsayılan __iter__geri dönüş, dizini C düzeyi bir değişkente saklar Py_ssize_t, bu nedenle yeterince beklerseniz, bu değişken en üst düzeye çıkar ve Python bir OverflowError'ı yükseltir . Bilgisayarlar 32 bit Python derlemesinde olmalıdır. Bilgisayarlar, 64 bit Python'da kimsenin buna çarpması için yeterince uzun süredir mevcut değildir.)


OverflowError ile ilgili olarak, bunu hem 64 hem de 32 bitte çalıştırdım ve haklısın, sadece 32 bitte gördüm.
Matthew Moisen

Bunu açıklayan belgeleri biliyor musunuz? Bu uygulamanın neden kararlaştırıldığını okumak istiyorum.
Matthew Moisen

3
@Matthew Expressions> Üyelik testi işlemleri , ayrıca nesne .__ içerir ve hemen üstündeki paragraf
wjandrea

4
@MatthewMoisen: Bu varsayılanlar orijinal davranış olduğunu forve in, tanıtımını predating __iter__ve __contains__. Burada ve burada Python 1.4 belgelerine bakın .
user2357112 Monica
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.