10

New to python, trying to create a card deck and want to implement a printing method for print(deck) => that gives a printed list of my cards.

My class PlayingCard has a str method which works fine to print a single card.

But when I create my Deck.cards object (which is a list of PlayingCard objects), I can't seem to print all the cards at once.

Tried replacing str with repr. Tried returning a list of strings in str

from enum import Enum

class Value(Enum):

    Two = 2
    Three = 3
    Four = 4
    Five = 5 
    Six = 6
    Seven = 7
    Eight = 8
    Nine = 9
    Ten = 10
    Jack = 11
    Queen = 12
    King = 13 
    Ace = 14

class Suit(Enum):

    Spades = 1
    Hearts = 2
    Clubs = 3
    Diamonds = 4


class PlayingCard():

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


    def __str__(self):
        return '{} of {}'.format(Value(self.value).name, Suit(self.suit).name)

class Deck():

    def __init__(self):
        self.cards=[PlayingCard(val,suit) for val in Value for suit in Suit]

    def __str__(self):
        return str(self.cards)


deck = Deck()
print(deck)

Returns

[<__main__.PlayingCard object at 0x000001875FEC0080>,
<__main__.PlayingCard object at 0x000001875FE9EE48>,
....
....
]
Torxed
  • 22,866
  • 14
  • 82
  • 131
  • Code looks ok, you're just confusing `__str__` with `__repr__`. Beware that you can override `__repr__` but it's hacky, you're not strictly supposed to, it breaks pickling etc. But it's fine for getting your basic debugging working, then just move the `__repr__` code to `__str__` when you've gotten it working. – smci May 04 '19 at 11:07

2 Answers2

5

You just need to replace the __str__ method of the PlayingCard class with a __repr__ method:

class PlayingCard():

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

    def __repr__(self):
        return '{} of {}'.format(Value(self.value).name, Suit(self.suit).name)

Alternatively you can change the __str__ method in the Deck class to get the string representation of every card:

class Deck():

    def __init__(self):
        self.cards=[PlayingCard(val,suit) for val in Value for suit in Suit]

    def __str__(self):
        return str([str(card) for card in self.cards])

Then you get the correct output with:

...

deck = Deck()
print(deck)

Output:
(The 2nd way will add quotes around every printed card)

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

When you call __str__ on a list object, it will go through every element of the list and call __repr__ on that object to get its representation.

So when you call print(deck), you get:

--> deck.__str__()
--> str(self.cards)
--> [card.__repr__() for card in self.cards]
ruohola
  • 21,987
  • 6
  • 62
  • 97
1

Be careful, repr is supposed to return python code that can recreate the object.

The way I would do it is to use a NamedTuple for PlayingCard

from typing import NamedTuple
class PlayingCard(NamedTuple):
    value: Value
    suit: Suit

*Note that the type hints are optional but come quite handy.

Then NamedTuple already implements repr and str so you don't need to reimplement anything.

LtWorf
  • 7,286
  • 6
  • 31
  • 45