22 Class and Methods III
1. Card objects
are fifty-two cards in a deck, each of which belongs to one of four
suits and one of thirteen ranks. The suits are Spades, Hearts,
Diamonds, and Clubs (in descending order in bridge). The ranks are Ace,
2, 3, 4, 5, 6, 7, 8, 9, 10, Jack, Queen, and King. Depending on the
game that you are playing, an Ace may be higher than King or lower than
If we want to define a new object to represent a playing
card, it is obvious what the attributes should be: rank and suit. It is
not as obvious what type the attributes should be. One possibility is
to use strings containing words like 'Spade' for suits and 'Queen' for
ranks. One problem with this implementation is that it would not be
easy to compare cards to see which had a higher rank or suit.
alternative is to use integers to encode the ranks and suits. In this
context, “encode” means that we are going to define a mapping between
numbers and suits, or between numbers and ranks. This kind of encoding
is not meant to be a secret (that would be “encryption”).
For example, this table shows the suits and the corresponding integer
code makes it easy to compare cards; because higher suits map to higher
numbers, we can compare suits by comparing their codes. The mapping for
ranks is fairly obvious; each of the numerical ranks maps to the
corresponding integer, and for face cards:
The Object diagram:
usual, the init method takes an optional parameter for each attribute.
The default card is the 2 of Clubs. To create a Card, you call Card
with the suit and rank of the card you want.
order to print Card objects in a way that people can easily read, we
need a mapping from the integer codes to the corresponding ranks and
suits. A natural way to do that is with lists of strings. We assign
these lists to class attributes:
Or you can do it in this way: Please make sure you understand the
differences between the one below and the one above:
If I change the arguments in the 'Card()' class call, I can have
WHY the 'print(cardie)' function can print out the results in a certain
format? The reason is the 'print()' function will call the '__str__()'
function automatically behind the scene.
2. Comparing cards
built-in types, there are relational operators (<, >, ==,
that compare values and determine when one is greater than, less than,
or equal to another. For programmer-defined types, we can override
the behavior of the built-in operators by providing a method named
__lt__, which stands for “less than”. __lt__ takes two parameters, self
and other, and returns True if self is strictly less than other.
correct ordering for cards is not obvious. For example, which is
better, the 3 of Clubs or the 2 of Diamonds? One has a higher rank, but
the other has a higher suit. In order to compare cards, you have to
decide whether rank or suit is more important. The answer might depend
on what game you are playing, but to keep things simple, we’ll make the
arbitrary choice that suit is more important, so all of the Spades
outrank all of the Diamonds, and so on.
3. Decks and printing the
know that there are 4 suits and 13 ranks. To printing out the deck, we
need to create a list of 'index pairs' to extract all the combination
of Suits&Pairs. Let's start with a small program. Let's create
index list first:
I used a nested 'for loop' to create these combinations.
Now we need these indices to extract all the real card names from the
you can use the join method on your delimiter, '\n':
Join many string with a new line between them:
If we comment the '__str__()' function, the printed results will not be
aligned in a single column:
Create a class with methods that can take 4 arguments: 'suit_1',
'rank_1', 'suit _2', 'rank_2' as the inputs and return a result like:
'Card 1 outranks Card 2'.
a. The suits are more important. Compare suits first and then compare the ranks.
b. Card importance:
Complete the following code. Then start a new instance named 'Jack',
set the balance for Jack, then withdraw some money, and deposit some
money into the balance to verify your code.