2017-09-05 22 views
3

我在阅读流利的Python如何将random.choice应用于我的自定义类?

代码1-1,在这里它构造了一个名为tUples的类并实现__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] 

但后来笔者采用random.choice选择从甲板

from random import choice 
deck = FrenchDeck() 
choice(deck) 

卡这是怎么工作?我不认为甲板是一个序列。

+1

Python使用[duck typing](https://en.wikipedia.org/wiki/Duck_typing):通过给你的类型一个长度和访问索引项目的方法,你*使它[一个序列](https://docs.python.org/3/glossary.html#term-sequence)。所以是的,'deck'是一个序列。 – poke

回答

1

实现__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想要的文件。 random.Random实例

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

选择(个体,SEQ)方法选择从非空序列的随机元素。

0

deck确实不是列表,通过documentation,任何对象,其类实现__getitem__可以被视为一个列表状物体,例如表示,序列号。由于实施__getitem__允许您使用诸如deck[i]之类的东西,因此您可以拨打choice(deck),因为choice(deck)所做的是它在0和len(deck)之间生成一个随机数i并返回deck(i)

+0

是的,使用了错误的词。我想用列表代替序列。将纠正我的错误,甚至没有看到它... – campovski

相关问题