파이썬 데이터 모델은 가능한 한 많이 핵심 프로토콜과 협업하겠다는 철할을 가지고 있고, 시퀀스의 경우 가장 단순한 객체를 사용하는 경우에도 파이썬은 최선을 다한다.
"""
abc.Sequence를 상속하지 않으며, 시퀀스 프로토콜 메서드 중 __getitem__()메서드 하나만 구현한다.
__getitem__()으로 부분 구현한 시퀀스 프로토콜, 항목에 접근할 수 있고, 반복할 수 있으며 in 연산자에서 사용할 수 있다.
"""
class Foo:
def __getitem__(self,pos):
return range(0,30,10)[pos]
f = Foo()
f[1]
for i in f: print(i)
iter()메서든ㄴ 아직 구현하지 않았지만, 대체 수단인 getitem()메서드가 구현되어 있으므로 Foo 객체를 반복할 수 있고, 파이썬 인터프리터는 0부터 시작하는 정수 인덱스로 getitem()메서드를 호출하여 객체 반복을 시도하기 때문이다.
파이썬은 Foo객체를 반복할만큼 충분히 똑똑하므로 Foo에 contains() 메서드가 구현되어 있지 않지만, 객체 전체를 조사해서 항목을 찾아냄으로써 in 연산자도 작동시킬 수 있다.
시퀀스 프로토콜의 중요성 때문에 iter()와 contains() 메서드가 구현되어 있지 않더라도 파이썬은 getitem() 메서드를 호출해서 객체를 반복하고 in 연산자를 사용할 수 있게 해준다.
import collections
Card = collections.namedtuple('Card', ['rank', 'suit'])
class FrenchDeck:
ranks = [str(n) for n in range(2,11)] + list('JQKA')
suits = 'spades diamonds clubs hearts'.split()
def __init__(self):
self._cards = [Card(rank,suit) for suit in self.suits
for rank in self.ranks]
def __len__(self):
return len(self._cards)
def __getitem__(self, position):
return self._cards[position]