2017-09-05 51 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

相關問題