Debugging in Python, part 8: Modeling playing cards
MP 149: In pursuit of logical errors.
Note: This post is part of an ongoing series about debugging in Python. The posts in this series will only be available to paid subscribers for the first 6 weeks. After that they will be available to everyone. Thank you to everyone who supports my ongoing work on Mostly Python.
Every bug we've looked at so far has resulted in a traceback. It's important to learn how to debug your code when you see a traceback, but that's not the only kind of bug you'll face. The more common, and often more difficult kind of bug you'll need to resolve is a logical error. A logical error doesn't cause your program to crash; instead it causes the program to generate incorrect output. These kinds of issues can be much harder to debug, because Python doesn't give you any insight into how to address them. You have to reason about what's happening, diagnose the issue, and come up with a fix.
Why focus on cards?
When I first started working on this post, I tried to introduce some logical errors into the strat_players.py project. It was hard to come up with any meaningful examples, because most of the logic in that project is implemented inside the pandas and Plotly libraries. We need a project with more of our own code in order to focus meaningfully on logical errors.
If you've never done so, I'd encourage you to write your own implementations of a playing card, a hand of playing cards, and a deck of cards. There are many ways to do this, and you'll almost certainly learn something by writing your own code to model this seemingly simple context. I'm going to walk through my own implementation of these three things, and then we'll use the resulting codebase to work through some logical errors in the final posts of this series.
These implementations aren't meant to be perfect or optimized. I'm choosing this context to close out the series because there's a lot of simple but subtle behavior to implement when working on card games. Choices that seem reasonable when modeling cards, hands, and decks can become surprisingly problematic once you start using your models. Some logical errors will almost certainly come up if you try to do this on your own, and it's easy to introduce a variety of logical errors into this kind of codebase. py-bugger doesn't currently allow you to generate logical errors in a project, but I'm looking forward to building that functionality into it over the coming months.

Modeling a playing card
The first thing we'll do is model a single playing card. Here's my first pass at a class called Card
:
This post is only available to paid subscribers at the moment. It will be available to everyone 6 weeks after posting. If you'd like to continue reading now, please support my work by signing up for a paid subscription.