import collections
import random
Card = collections.namedtuple('Card', ["color","num"])
class Deck(object):
nums = [str(i) for i in range(2,11)] + list("AJQK")
colors = ["heart", "spade", "diamond", "club"]
def __init__(self):
self._cards = [Card(color,num) for color in Deck.colors for num in Deck.nums]
def __getitem__(self, index):
return self._cards[index]
def __len__(self):
return len(self._cards)
d = Deck()
print(d[0])
print(d[1])
print(d[51])
print(len(d))
for i in d:
print(i)
print(d[1:5])
print(random.choice(d))
print(Card('heart','Q') in d)
def setitem(deck, index, card):
deck._cards[index] = card
Deck.__setitem__ = setitem
random.shuffle(d)
在需要创建大量简单类(如Card,只有两个属性需要访问)的实例的时候,使用namedtuple十分直观,简洁。
__len__方法为使用len()函数提供了依据。CPython中是如何实现len()函数的呢?
实际上,在源码中,cpython的一切对象都源自于PyVarObject ,这其中有个变量ob_size。使用len()可以直接将它返回,更快。__getitem__方法的神奇之处在于:实现了这一方法后,实例对象可以用for迭代,可以用index访问,可以切片,还可以使用in判断是否存在,更甚者可以使用random.choice(),当然也可使用sorted或reversed.
这是由于实现了__getitem__后python解释器,可以从index=0开始迭代,这就实现了iter的功能,同时,也可以从index=0开始扫描进而实现了in的功能。- 但是没有__setitem__方法,实例不能完成random.shuffle().
可以在类中进行补充,也可以动态绑定。
def setitem(deck, index, card):
deck._cards[index] = card # 不能是deck[index]会形成无穷递归
>>>Deck.__setitem__ = setitem # 类方法的绑定