1

This is exercise 18.2 from "Think Python" book. There is a Class called Deck that creates a deck of cards as a list of tuples [(0,1), (0, 2)...]. The class has defined inner functions shuffle() and sort(). The shuffle() function works correct but when I try to sort the deck the fuction sort() I wrote does not return sorted deck.

I have no idea why is that. Any hint what am I doing wrong?

class Deck(object):
    """Represents deck of cards
        attributes: list of cards
    """
    def __init__(self):
        self.cards = []
        for suit in range(4):
            for rank in range(1, 14):
                card = Card(suit, rank)
                self.cards.append(card)

    def __str__(self):
        res = []
        for card in self.cards:
            res.append(str(card))
        return '\n'.join(res)

    def pop_card(self):
        return self.cards.pop()

    def add_card(self, card):
        self.cards.append(card)

    def shuffle(self):
        random.shuffle(self.cards)

    def sort(self):
        self.cards.sort()


new_deck = Deck()
print '>>>>>>>>>>>>>>>>>>>>new deck:'
print new_deck

new_deck.shuffle()
print '>>>>>>>>>>>>>>>>>>>>shuffled deck:'
print new_deck

new_deck.sort()
print '>>>>>>>>>>>>>>>>>>>>sorted deck:'
print new_deck

1 Answer 1

1

You are missing the definition of Card - also you are creating instances of Card instead of using tuple. The sort() function sorts tuples element-wise, using the next element one when a draw on the first happens:

[ (0,1),(0,-2) ].sort() 

results in

[ (0,-2),(0,1) ] # because draw on (0,_)

For your Card's class python does not know how to sort it, so it uses the id() function (unless you tell it how to sort itself, see below).

You can either define a key for your call to sort(...) or define Card.__lq__() method on your cards so it does not use id() when sorting cards:

import random

class Card(object):
    # fancier output
    s = {0:"hearts",1:"diamonds",2:"clubs",3:"spades"}
    r = {i:v for i,v in enumerate( [ "Ace","2","3","4","5","6","7","8",
                                     "9","10","Jack","Queen","King"],1)}
    def __init__(self, suit,rank):
        self.suit = suit
        self.rank = rank

    def __str__(self):
        return "{} of {}".format(Card.r[self.rank],Card.s[self.suit])

    def __repr__(self):
        return str(self)

    # UNCOMMENT to not need the sort-key() in Deck
    # def __lt__(self,other):
    #    return (self.suit,self.rank) < (other.suit, other.rank)

class Deck(object): 
    # keep the rest of your code, fix this: 
    # or uncomment __lq__() in Cards (which would be the prefered 
    # way to do it) and leave your method as is
    def sort(self):
        # tell sort to sort based on what key 

        self.cards.sort(key = lambda x: (x.suit, x.rank))


new_deck = Deck()
print '# new deck:'
print new_deck

new_deck.shuffle()
print '# shuffled deck:'
print new_deck

new_deck.sort()
print '# sorted deck:'
print new_deck

Output (shortened):

# new deck:
Ace of hearts   ... up to ...  King of hearts
Ace of diamonds ... up to ...  King of diamonds
Ace of clubs    ... up to ...  King of clubs
Ace of spades   ... up to ...  King of spades

# shuffled deck:
6 of hearts
7 of spades
# ... snipp the remaining mixed cards ...
2 of hearts
King of diamonds

# sorted deck:
Ace of hearts   ... up to ...  King of hearts
Ace of diamonds ... up to ...  King of diamonds
Ace of clubs    ... up to ...  King of clubs
Ace of spades   ... up to ...  King of spades

See also:

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you very, very much Patrick for your reply. Indeed both of your solutions work perfectly. I have also tried to implement cmp function instead of lt within Card class and it works perfectly too with self.cards.sort(). However I also took a look at terryjbates repository [github.com/terryjbates/think-python/blob/master/chapter-18/… and I can't figure out why in the sort function he inputs self.cards.sort(cmp=Card.__cmp__). Is it pythonic to add this argument 'cmp=Card.__cmp__' within sort() function?
@halny normally you do not use the methods with __dunder__() directly .. mostly you use len() instead of __len__, iter() instead of __iter__() etc. the __cmp__() is a method he created on the card and when sorting the deck he tells the sort methdod to use that one for sorting - it is similar to the key in self.cards.sort(key = lambda x: (x.suit, x.rank)) - but that is the python3 sort function syntax. I am a bit rusty on 2.7. cmp() is from python 2 - and got changed to the key-function
Essentially both are providing the "What to use for sorting function" to the list.sort(...) method

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.