'How does a Python class within another class work w/o Inheritance? (Python Beginner)

I'm a python beginner just ran threw a book that includes this MiniProject at the very end.The exercise reads:

Your task is to create a deck of cards class. The deck of cards class should use another class internally, a card class. Your requirements are:

  • The Deck class should have a deal method to deal w/ a single card from the deck
  • After a card is dealt, it is removed from the deck
  • There should be a shuffle method that makes sure the deck of cards has all 52 cards and then rearranges them randomly
  • The Card class should have a suit (Hearts, Diamonds, Clubs, Spades) and a value (A, 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K)

The provided solution is as follows:

from random import shuffle

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

    def __repr__(self):
        return "() of ()".format(self.value, self.suit)


class Deck:
    def __init__(self):
        suits = ['Hearts', 'Diamonds', 'Clubs', 'Spades']
        values = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']
        self.cards = [Card(suit, value) for suit in suits for value in values]

    def __repr__(self):
        return "Cards remaining in deck: ()".format(len(self.cards))

    def shuffle(self):
        if len(self.cards) < 52:
            raise ValueError("Only full decks can be shuffled")
            shuffle(self.cards)
            return self

    def deal(self):
        if len(self.cards) == 0:
            raise ValueError("All cards have been dealt")
            return self.cards.pop()

Q1: I can follow the individual methods but don't have a clue how to utilize this correctly.

I've tried to use the Card class with:

card = Card("Diamonds", "K")
print(card)

The output of the above is: () of ().

Q2: How does __repl__ work and how do we call it?

I'm sorry about the length. I appreciate any help and time with the issue. Any added clarity, on how to interpret what's going on, is greatly appreciated.



Solution 1:[1]

card = Card("Diamonds", "K")
print(card)

This final code is correct. The repr method is a special built-in function that defines how an object is REPResented, e.g what the print function will show.

The way I think about it is that print(card) is equivalent to print(card.__repr__()).

The problem you are having is that you have an issue in your repr methods. They should look like this:

  • card
def __repr__(self):
        return "{} of {}".format(self.value, self.suit)
  • deck
def __repr__(self):
        return "Cards remaining in deck: {}".format(len(self.cards))

I would also change the shuffle and deal functions as they will create inaccessible code warnings. Avoid having code in the same block after raising an error.

def shuffle(self):
    if len(self.cards) == 52:
        shuffle(self.cards)
        return self
    else:
        raise ValueError("Only full decks can be shuffled")

def deal(self):
    if len(self.cards) != 0:
        return self.cards.pop()
    else:
        raise ValueError("All cards have been dealt")

Solution 2:[2]

from random import shuffle

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

    def __repr__(self):
        return "(%s,%s)" %(self.value, self.suit)


class Deck:
    def __init__(self):
        suits = ['Hearts', 'Diamonds', 'Clubs', 'Spades']
        values = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']
        self.cards = [Card(suit, value) for suit in suits for value in values]
        for i in self.cards:
            print(i)

    def __repr__(self):
        return "Cards remaining in deck: {}".format(len(self.cards))
    
    def shuffle(self):
        if len(self.cards) == 52:
            shuffle(self.cards)
            return self.cards
        else:
            return("Only full decks can be shuffled")

    def deal(self):
        if len(self.cards) != 0:
            return self.cards.pop()
        else:
            return("All cards have been dealt")

d=Deck()
print("Deck created")

print("\n \nShuffling the deck")
x=d.shuffle()
for i in x:
    print(i)
a=int(input("\n \nEnter 1 to deal the cards \n"))

while(a==1):
    print(d.deal())
    print(d)
    a=int(input("Enter 1 to deal the cards (or) any key to discontinue \n"))
print(d.shuffle())

Solution 3:[3]

from random import shuffle

class Card:

def__init__(self, suit, value):

self.suit = suit

self.value = value

def repr(self):

return "(%s,%s)" %(self.value, self.suit)

class Deck:

def init(self):

suits = ['Hearts', 'Diamonds', 'Clubs', 'Spades']

values = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']

self.cards = [Card(suit, value) for suit in suits for value in values]

for i in self.cards:

print(i)

def repr(self):

return "Cards remaining in deck: {}".format(len(self.cards))

def shuffle(self):

if len(self.cards) == 52:

shuffle(self.cards)

return self.cards

else:

return("Only full decks can be shuffled")

def deal(self):

if len(self.cards) != 0:

return self.cards.pop()

else:

return("All cards have been dealt")

d=Deck()

print("Deck created")

print("\n \nShuffling the deck")

x=d.shuffle()

for i in x:

print(i)

a=int(input("\n \nEnter 1 to deal the cards \n"))

while(a==1):

print(d.deal())

print(d)

a=int(input("Enter 1 to deal the cards (or) any key to discontinue \n"))

print(d.shuffle())

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Angelo Giacco
Solution 2 Raksha Saini
Solution 3 AMAN SAINI