from collections import namedtuple
Card = 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 suit in self.suits
for rank in self.ranks]
def __len__(self):
return len(self._cards)
def __getitem__(self, position):
'''
delegates to [] operator, so supports slicing
it also becomes iterable, reverse, sorted can be called upon
'''
return self._cards[position]
suit_values = dict(spades=3, hearts=2, diamonds=1, clubs=0)
def spades_high(card):
rank_value = FrenchDeck.ranks.index(card.rank)
return rank_value * len(suit_values) + suit_values[card.suit]
if __name__ == '__main__':
deck = FrenchDeck()
print('Deck length', len(deck))
print(deck[0])
print(deck[-1])
print(deck[12::13])
for card in sorted(deck, key=spades_high):
print(card)
Special methods are usually called by python interpreter.
If you need to invoke a special method like __len__, __getitem__, etc., it is better to call related builtin method like len, iter, str, etc. Built-in methods also provide other related services. It is always good to call built-in methods because they usually invoke Cpython code directly instead of method(special) call which are time consuming due to stack handling and many more related tasks join the picture.
Write a comment ...