我正在读流利的Python。你知道吗
代码1-1,在这里它用namedtuples构造一个类并实现__len__
和__getitem__
。你知道吗
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 rank in self.ranks for suit in self.suits]
def __len__(self):
return len(self._cards)
def __getitem__(self, position):
return self._cards[position]
但后来作者使用随机选择从牌组中选择一张牌
from random import choice
deck = FrenchDeck()
choice(deck)
这是怎么回事?我不认为甲板是一个序列。你知道吗
deck
确实不是一个列表,但是如documentation所述,任何类实现__getitem__
的对象都可以被视为一个类似列表的对象,例如序列。因为实现__getitem__
允许deck[i]
这样的操作,所以可以调用choice(deck)
,因为choice(deck)
的作用是在0和len(deck)
之间生成一个随机数i
,并返回deck(i)
。你知道吗random.choice
从非空序列中获取一个随机元素。如果实现__getitem__
,python can use that to treat your object as a sequence by indexing,它就是这样做的。你知道吗实现
__getitem__
使您的类具有可移植性。观察:如果类没有
__iter__
方法而是__getitem__
方法,则Python在被迫这样做时,会从一个实例构造一个迭代器,该实例尝试通过__getitem__
访问其元素。它从索引0开始,并在抛出IndexError
时结束。你知道吗但是,由于
LegacyIterable
实例没有__len__
方法,因此它们还没有正式算作序列,random.choice
会抱怨然而,一旦我们给它一个
__len__
方法,实例就可以算作序列,根据它的文档,这就是random.choice
想要的。你知道吗相关问题 更多 >
编程相关推荐