Data Classes for Comparison
00:00
Comparison. In many card games, cards are compared to each other. For instance, in a typical trick taking game, the highest card takes the trick. As it is currently implemented, the PlayingCard
class does not support this kind of comparison.
00:38
This is, however, seemingly easy to rectify. The @dataclass
decorator has two forms. So far, you’ve used this simple form where @dataclass
is specified without any parentheses or parameters. However, you can also give parameters to the decorator in parentheses.
00:58
These are the parameters that are supported. init
: add an .__init__()
method. The default is True
. repr
: add a .__repr__()
method.
01:08
The default is True
. eq
: add an .__eq__()
method. The default is True
. order
: add ordering methods.
01:17
The default here is False
. unsafe_hash
: force the addition of a .__hash__()
method. The default is False
. frozen
: if True
, assigning to fields raises an exception. The default is False
.
01:35
So, let’s see if we can make use of order
to solve our problem.
02:01
After setting order
to be True
, instances of PlayingCard
can be compared. How are the two cards compared, though? You’ve not specified how the ordering should be done, and for some reason Python seems to believe that a queen is higher than an ace.
02:35
It turns out that data classes compare objects as if they were tuples of their fields. In other words, a queen is higher than an ace because 'Q'
comes after 'A'
in the alphabet.
02:53
That doesn’t really work for us. Instead, we need to define some kind of sort index that uses the order of RANKS
and SUITS
, something like seen onscreen now.
03:35
For PlayingCard
to use this sort index for comparisons, we need to add a field .sort_index
to the class. However, this field should be calculated from the other fields .rank
and .suit
automatically.
03:48
This is exactly what the special method .__post_init__()
is for. It allows for special processing after the regular .__init__()
method is called.
04:43
Note that .sort_index
is added as the first field of the class. This way, the comparison is first done using .sort_index
, and only if there are ties are any of the other fields used. Using field()
, you must also specify that .sort_index
should not be included as a parameter in the .__init__()
method, because it’s calculated from the .rank
and .suit
fields.
05:06
To avoid confusing the user about this implementation detail, it’s probably also a good idea to remove .sort_index
from the repr
of the class, as has been done in the code you’ve just seen. Finally, aces are high.
05:39 You can now easily create a sorted deck. And if you don’t care about sorting, this is how you draw a random hand of ten cards. In the next section of the course, you’ll take a look at how to make data classes immutable.
Become a Member to join the conversation.
Ariba S on June 12, 2024
Feeling a bit confused about how the different sort index is used by dataclass decorator?