0

I am designing a deck class that has init() method with initially has an empty list. Then I append my cards to the list. I am trying to create an x instance and access the shuffled version of the deck of cards. I know there are many solutions posted already. I just want to understand with my logic I am able to print the address of the card elements and not the deck itself. While trying to debug ,I am not understanding whether print(x.cards_in_deck) is printing the location or the x.shuffle... .Any good reference for Pycharm debugging will also be highly appreciated.

suits = ('Hearts', 'Diamonds', 'Spades', 'Clubs')
ranks = ('Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine', 'Ten', 'Jack', 'Queen', 'King', 'Ace')
values = {'Two':2, 'Three':3, 'Four':4, 'Five':5, 'Six':6, 'Seven':7, 'Eight':8, 'Nine':9, 'Ten':10, 'Jack':10,
         'Queen':10, 'King':10, 'Ace':11}
class Card:

    def __init__(self,suit,rank):
        self.suit = suit
        self.rank = rank


    def __str__(self):
        return self.rank +' of '+self.suit
class Deck:

    def __init__(self):

        self.cards_in_deck = []
        for suit in suits:
            for rank in ranks:
                self.cards_in_deck.append(Card(suit, rank))
        #return self.cards_in_deck

    def __str__(self):
        # for card in Deck.cards_in_deck:
        #     return(card)
        return self.cards_in_deck

    def shuffle_cards(self):
        return random.shuffle(self.cards_in_deck)

x = Deck()
print(x.cards_in_deck,sep ='\n')
print(x.shuffle_cards(),sep = '\n')
Patrick Artner
  • 50,409
  • 9
  • 43
  • 69
Mahantesh
  • 53
  • 7

2 Answers2

2

The first print statement will print the value of the instance variable "cards_in_deck" on your Deck object. The type of variable is a list, so when it's printed, it'll look like:

[Two of Hearts, Three of Hearts, <more items>, King of Clubs, Ace of Clubs]

The second print statement will call the shuffle_cards method on the Deck object, and print whatever that method returns. That method returns the result of calling random.shuffle on the list. That result is a new list, that would be the shuffled cards.

Now, each of these print statements is printing a list object, which is what the text above looks like. If you wanted to print each individual card, you would need to loop through the cards, similarly to how you loop through your lists when initializing the deck. So, you could do something like:

for card in x.cards_in_deck:
    print(card)

This would print each card's name on a new line each.

EDIT: I did not see you were using __str__ and not __repr__ in your Card class. When printing a list, Python uses the __repr__ method to determine what to put in the spot in the list. See: Confused about __str__ on list in Python

kuhnertdm
  • 144
  • 5
  • Sir ,I am unable to print the list.It is just printing the list item location. – Mahantesh Jan 01 '19 at 00:17
  • I am getting output of something this sort...[<__main__.Card object at 0x00000208C3792860>, <__main__.Card object at 0x00000208C37928 – Mahantesh Jan 01 '19 at 00:18
  • Is there any pointer method like in c to catch that address and print the values ,since if what you are saying is true ,then I always need to add __str__() or __repr__() method to the class!!! – Mahantesh Jan 01 '19 at 00:39
  • Is it always necessary the __str__() and __repr__() method return string type to print?If not necessary ,then we can create our own function convert the return type and print as function(value). Why are they specially called __str__() and __repr__()? Please forgive if u find silly,I am a newbee !!! – Mahantesh Jan 01 '19 at 00:53
  • You may be thinking of it the wrong way. It's still printing the object, not the address. However, if \_\_repr\_\_ isn't defined on the class, it doesn't know text should be used to represent that object. So it just ends up printing what it knows: that it's a Card object at that address. If you're making a Python class that you think will be called with print, then you should implement \_\_repr\_\_ on it. – kuhnertdm Jan 01 '19 at 00:55
  • def __str__(self): deck_of_cards = [] for card in self.cards_in_deck: deck_of_cards.append(card) return ('\n'.join(deck_of_cards)) .I tried using ' '.join().Got the error as TypeError: sequence item 0: expected str instance, Card found .Can u tell me whats wrong? – Mahantesh Jan 01 '19 at 01:11
2

If you print a list, any item in the list is printed using it's repr(). You can define what is used by specifying the __repr(self)__ method of your class - you may also want to define the __str__(self) method of your class. If you do not specify a "special" repr and str python will create default ones for you which may not print what You want it to.

See: Difference between __str__ and __repr__?

Both should return a string - what you are not doing, you return a list for your Deck class which violates the contract of these method's:

Doku:

Both descriptions say:

The return value must be a string object.

and give some more informations on them.


Fix:

suits = ('Hearts', 'Diamonds', 'Spades', 'Clubs')
ranks = ('Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine', 'Ten', 'Jack', 'Queen', 'King', 'Ace')
values = {'Two':2, 'Three':3, 'Four':4, 'Five':5, 'Six':6, 'Seven':7, 'Eight':8, 'Nine':9, 'Ten':10, 'Jack':10,
         'Queen':10, 'King':10, 'Ace':11}

import random

class Card:
    def __init__(self,suit,rank):
        self.suit = suit
        self.rank = rank

    def __str__(self):
        return self.rank +' of '+self.suit
    def __repr__(self):
        return self.rank +' of '+self.suit

class Deck:
    def __init__(self):
        # always create shuffled decks
        self.create_new_deck()

    def __str__(self):  
        # return a string here, not a list
        # join only takes strings so you need to stringify each card beforehand
        return ', '.join(str(c) for c in self.cards_in_deck)        

    def __repr__(self):
        return ', '.join(str(c) for c in self.cards_in_deck)

    # create a new deck and shuffle it immediately
    def create_new_deck(self):
        self.cards_in_deck = [Card(s, r) for s in suits for r in ranks]
        random.shuffle(self.cards_in_deck)

x = Deck()
print(str(x)) 

Output:

King of Clubs, Ace of Diamonds, Seven of Spades, Ace of Spades, Three of Hearts, 
Eight of Hearts, Five of Clubs, Four of Spades, King of Diamonds, Five of Hearts, 
Eight of Spades, Three of Diamonds, Three of Spades, Six of Diamonds, 
Eight of Diamonds, Queen of Hearts, Ace of Hearts, Ten of Clubs, Two of Diamonds, 
Six of Clubs, King of Hearts, Seven of Clubs, Queen of Clubs, King of Spades, 
Nine of Diamonds, Six of Hearts, Nine of Clubs, Queen of Diamonds, Queen of Spades,
 Ten of Diamonds, Seven of Hearts, Ten of Hearts, Eight of Clubs, Ace of Clubs,
Jack of Clubs, Nine of Spades, Four of Diamonds, Seven of Diamonds, Nine of Hearts,
 Two of Clubs, Jack of Hearts, Jack of Spades, Jack of Diamonds, Two of Spades, 
Ten of Spades, Four of Hearts, Three of Clubs, Six of Spades, Five of Spades, 
Two of Hearts, Five of Diamonds, Four of Clubs

Debugging:

Patrick Artner
  • 50,409
  • 9
  • 43
  • 69