프로그래밍중급 Python 개발자

사용자 정의 객체에 대한 'in' 연산자는 어떻게 작동하나요? 'x in your_obj' 표현식을 작동시키기 위해서는 클래스에서 무엇을 구현해야 하나요? 성능 문제와 예기치 않은 오류를 피하려면 어떻게 해야 하나요?

Hintsage AI 어시스턴트로 면접 통과

답변.

Python에서 in 연산자는 요소가 컬렉션에 포함되어 있는지를 정의합니다. 사용자 정의 객체의 경우 x in your_obj 구문을 지원하려면 메서드 __contains__를 구현해야 합니다. 이 메서드가 없으면 인터프리터는 __iter__ 또는 __getitem__을 사용하여 객체를 반복하려고 시도하지만, 그 동작과 효율성은 다를 수 있습니다.

예시:

class MyBag: def __init__(self, items): self.items = items def __contains__(self, value): return value in self.items bag = MyBag([1,2,3]) print(2 in bag) # True print(5 in bag) # False

만약 __iter__만 구현하거나 심지어 __getitem__만 구현하더라도 in은 작동하지만, 덜 효율적이거나 때로는 예상과 다르게 작동할 수 있습니다.

주의사항: 만약 컬렉션이 거대하고 검사 방식이 단순히 리스트 전체를 순회하는 방식을 사용한다면 성능 문제에 직면할 수 있습니다. 빠른 검사를 위해 예를 들어 집합을 사용할 수 있습니다.

트릭 질문.

in 연산자의 올바른 작동을 위해 단지 __iter__만 구현하는 것으로 충분한가요? 동작은 어떻게 바뀔까요?

답변:

  • __contains__가 없으면, Python은 __iter__ (있다면)를 사용하여 요소를 반복하려고 하거나 __getitem__을 사용하여 인덱스 0부터 시작하여 IndexError 예외가 발생할 때까지 시도합니다.
  • 이러한 동작은 덜 효율적이며, 메서드에 오타가 있는 경우 무한 루프나 예외를 유발할 수 있습니다.

예시:

class Weird: def __getitem__(self, idx): if idx < 3: return idx raise IndexError w = Weird() print(2 in w) # True print(5 in w) # False

이 주제에 대한 미세한 차이로 인한 실제 오류 사례.


이야기

한 프로젝트에서 사용자 정의 엔티티 저장 컨테이너는 __iter__만 재정의하고 __contains__를 구현하는 것을 잊었습니다. in 연산자는 큰 컬렉션에서 지연이 발생할 뿐만 아니라, 반복자가 StopIteration이 아닌 예외를 잘못 던질 때 신비한 오류로 인해 갑자기 실패하기 시작했습니다.


이야기

요소가 인덱스에 따라 "즉석에서" 계산되는 클래스에 대해 개발자는 __getitem__만 구현했습니다. 큰 x로 x in obj를 검사하려고 시도했을 때 긴 루프와 메모리 부족 오류가 발생했습니다. in은 IndexError를 만날 때까지 모든 인덱스를 증가시키며 검사하기 때문에입니다.


이야기

한 프로젝트에서는 in을 위해 __iter__만 사용하는 맞춤형 사전이 구현되었습니다. 이것은 100,000개의 키에 대해 검색이 밀리초가 아닌 몇 초가 걸리는 문제를 초래했습니다. 이는 표준 dict에서 __contains__가 효율적으로 구현되어 있기 때문입니다.