用一个非常简单的例子来展示如何实现 __getitme__和 __len__这两个特殊方法
示例 1-1 一摞有序的纸牌
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]
首先,我们用 collections.namedtuple 构建了一个简单的类来表示一张纸牌。(namedtuple 用以构建只有少数属性但是没有方法的对象,比如数据库条目。)
如下所示,利用 namedtuple ,我们可以很轻松地得到一个纸牌对象:
>>> beer_card = Card('7', 'diamonds')
>>> beer_card
Card(rank='7', suit='diamonds')
__len__方法
FrenchDeck 这个类,可以用 len() 函数来查看一叠牌有多少张:
>>> deck = FrenchDeck()
>>> len(deck)
52
__getitem__方法
通过 __getitem__方法, 可以实现:从一叠牌中抽取特定的一张纸牌,比如说第一张或最后一张,是很容易的:deck[0] 或 deck[-1] 。
>>> deck[0]
Card(rank='2', suit='spades')
>>> deck[-1]
Card(rank='A', suit='hearts')
random.choice函数
实现随机抽取一张纸牌
>>> from random import choice
>>> choice(deck)
Card(rank='3', suit='hearts')
>>> choice(deck)
Card(rank='K', suit='spades')
>>> choice(deck)
Card(rank='2', suit='clubs')
总结
可以体会到通过实现特殊方法来利用 Python 数据模型的两个好处。
1) 作为你的类的用户,他们不必去记住标准操作的各式名称(“怎么得到元素的总数?是 .size() 还是 .length() 还是别的什么?”)。
2) 可以更加方便地利用 Python 的标准库,比如 random.choice 函数,从而不用重新发明轮子。