如何申请随机选择去我的定制课?

2024-10-02 16:23:00 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在读流利的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)

这是怎么回事?我不认为甲板是一个序列。你知道吗


Tags: inimportselfforlendefcardcollections
3条回答

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__使您的类具有可移植性。观察:

>>> class LegacyIterable(object):
...     def __init__(self):
...         self._list = ['a', 'b', 'c']
...     def __getitem__(self, item):
...         return self._list[item]
... 
>>> x = LegacyIterable()
>>> for e in x:
...     print e
... 
a
b
c

如果类没有__iter__方法而是__getitem__方法,则Python在被迫这样做时,会从一个实例构造一个迭代器,该实例尝试通过__getitem__访问其元素。它从索引0开始,并在抛出IndexError时结束。你知道吗

但是,由于LegacyIterable实例没有__len__方法,因此它们还没有正式算作序列,random.choice会抱怨

TypeError: object of type 'LegacyIterable' has no len()

然而,一旦我们给它一个__len__方法,实例就可以算作序列,根据它的文档,这就是random.choice想要的。你知道吗

>>> LegacyIterable.__len__ = lambda x: 3
>>> choice(LegacyIterable())
'c'

choice(self, seq) method of random.Random instance
Choose a random element from a non-empty sequence.

相关问题 更多 >