Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Hint: You can adjust the default video playback speed in your account settings.
Hint: You can set your subtitle preferences in your account settings.
Sorry! Looks like there’s an issue with video playback 🙁 This might be due to a temporary outage or because of a configuration issue with your browser. Please refer to our video player troubleshooting guide for assistance.

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.