What is the best way to create a deck of cards?

I propose you a solution with a basic class usage.

First, let's make a Card class:

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

Then, let's make a list of colors:

colors = ['heart', 'diamonds', 'spades', 'clubs']

Finally, let's build your deck with a list comprehension:

deck = [Card(value, color) for value in range(1, 14) for color in colors]

The Card class is only a wrapper, just to manipulate cards instead of tuples, which feels more natural.

In this current state, it's almost equivalent to renaming the tuple type... Basically, it only consists in a constructor, __init__, that sets the attributes of the instance.

So when I call Card(value, color) in the list comprehension, so for example Card(11, 'spades'), a new instance of the Card class is created, which has its value attribute set to 11, and its color attribute set to 'spades'.

I recommend you read some tutorial about OOP for an in-depth understanding of the concepts.


Now, you can try and improve this idea, for instance by using a more detailed values list instead of the range(1, 14):

values = ['ace', '2', ..., 'king']

Another approach can be done using namedtuple from collections module, like this example:

from collections import namedtuple

Card = namedtuple('Card', ['value', 'suit'])
suits = ['hearts', 'diamonds', 'spades', 'clubs']
cards = [Card(value, suit) for value in range(1, 14) for suit in suits]

And you can access to the values like this:

print(cards[0])
>>> Card(value=1, suit='hearts')
print(cards[0].value, cards[0].suit)
>>> 1 hearts

You can represent your deck as a list of tuples. Which is a lighter weight alternative to classes. In dynamic languages like python, you will often do this to avoid the boilerplate code incurred by defining your own classes.

import itertools
import random

vals = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'jack', 'queen', 'king', 'ace']
suits = ['spades', 'clubs', 'hearts', 'diamonds']

deck = list(itertools.product(vals, suits))

random.shuffle(deck)

for val, suit in deck:
    print('The %s of %s' % (val, suit))

You may wish to represent the card values by an integer, this could easily be achieved by altering the input list.

Tags:

Python