<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 A deck as a sequence of cards
Step1:  Deck responds to the len() function
Step2:  Reading specific cards from the deck is provided by the getitem method
Step3:  Get a random item from a sequence
Step4:  Deck supports slicing
Step5:  Deck is iterable
Step6:  Deck can also be iterated in reverse
Step7:  in operator works because deck is iterable
if a collection does has no contains method, the in operator does a sequential scan
Step8:  Sorting
<ASSISTANT_TASK:>
Python Code:
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 suit in self.suits
                                        for rank in self.ranks]
        
    def __len__(self):
        return len(self._cards)
    
    def __getitem__(self, position):
        return self._cards[position]
    
beer_card = Card('7', 'diamonds')
beer_card
Explanation: A deck as a sequence of cards
End of explanation
deck = FrenchDeck()
len(deck)
Explanation: Deck responds to the len() function
End of explanation
deck[0]
deck[-1]
Explanation: Reading specific cards from the deck is provided by the getitem method
End of explanation
from random import choice
choice(deck)
choice(deck)
choice(deck)
Explanation: Get a random item from a sequence: random.choice
End of explanation
deck[:3]
for idx, card in enumerate(deck):
    print(idx, ' -> ', card)
deck[12::13]
Explanation: Deck supports slicing: getitem delegates to the [] operator
Top three cards in a brand new deck
End of explanation
for card in deck:
    print(card)
Explanation: Deck is iterable: getitem special method
End of explanation
for card in reversed(deck):
    print(card)
Explanation: Deck can also be iterated in reverse
End of explanation
Card('Q', 'hearts') in deck
Card('A', 'beasts') in deck
Explanation: in operator works because deck is iterable
if a collection does has no contains method, the in operator does a sequential scan
End of explanation
suit_values = dict(spades=3, hearts=2, diamonds=1, clubs=0)
suit_values
def spades_high(card:Card):
    rank_value = FrenchDeck.ranks.index(card.rank)
    return rank_value * len(suit_values) + suit_values[card.suit]
spades_high(Card('2', 'clubs'))
spades_high(Card('A', 'spades'))
for card in sorted(deck, key=spades_high):
    print(card)
Explanation: Sorting: Ranking cards by rank
End of explanation
<END_TASK>