파이썬 __getitem__ 및 연산자에서 이상한 동작이 발생합니다.


34

다음 동작을 설명하는 내용 :

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

답변:


45

객체에 __contains__구현 이 없으면 in기본적으로 다음과 같이 작동하는 기본값으로 돌아갑니다.

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

그리고 객체에 __iter__구현 이 없으면 for기본적으로 다음과 같이 작동하는 기본값으로 돌아갑니다.

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

이 기본값은 객체가 시퀀스가 ​​아닌 경우에도 사용됩니다.

귀하 1 in f5 in f테스트에 대한 기본 폴백 (fallback)를 사용 in하고 for관찰 된 행동에지도. 즉시 1 in f찾지 1__getitem__결코 반환하지 5않으므로 5 in f영원히 실행됩니다.

(실제로 Python의 참조 구현에서 기본 __iter__폴백은 인덱스를 C 유형의 type 변수 유형 Py_ssize_t으로 저장하므로 오래 기다리면 해당 변수가 최대치가되고 Python에서 OverflowError가 발생 합니다. 32 비트 Python 빌드에 있어야합니다. 컴퓨터는 64 비트 Python에서 그 누구도 칠 수있을 정도로 오래 존재하지 않았습니다.)


OverflowError와 관련하여 64 비트와 32 비트 모두에서 이것을 실행했으며 32 비트에서만 보았습니다.
Matthew Moisen

이것을 설명하는 문서를 알고 있습니까? 이 구현이 결정된 이유를 읽고 싶습니다.
Matthew Moisen


4
@MatthewMoisen :이 기본값의 원래 동작이었다 forin,의 도입을 낳은 __iter__하고 __contains__. 여기여기 에서 Python 1.4 설명서를 참조 하십시오 .
user2357112는
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.