Harnessing the Power of Python 3.10’s Match-Case: A Journey Through Structural Pattern Matching

Marco Sanguineti
4 min readJun 15, 2023

Leveraging the Match-Case Statement to Simplify Code Logic and Enhance Readability

Python 3.10 introduced a powerful new language feature: Structural Pattern Matching. This feature adds a match statement and case clauses to the language, allowing patterns to be used in conditionals and variable assignments. It's a feature that's been prevalent in other languages such as Scala and Rust, and it introduces a new way of handling data processing tasks that might be more efficient or clearer than traditional methods.

Adventure Game Artwork — Image by Author (Dalle 2)

Basics of Structural Pattern Matching

To understand how structural pattern matching works in Python, it’s useful to start with a simple example. Consider the following code snippet:

match x:
case 0:
print("zero")
case 1:
print("one")
case _:
print("more")

Here, x is the subject being matched, and the case clauses specify different patterns for which the match statement checks. Each pattern is followed by a colon and a block of code that is executed if the pattern matches the subject. The _ is a special pattern that always matches, making it a useful default or catch-all case.

Structural pattern matching goes beyond simple value comparisons. It can match data structures and bind variables for further use in the case block. For example:

match point:
case (0, 0):
print("Origin")
case (0, y):
print(f"Y={y}")
case (x, 0):
print(f"X={x}")
case (x, y):
print(f"X={x}, Y={y}")
case _:
print("Not a point")

In this example, point is a tuple, and the patterns are tuples of the same size. When a pattern matches the structure of point and the values of all elements, the corresponding block of code is executed.

Implementing a Text-Based Adventure Game

Can we use structural pattern matching to create a new simple text-based adventure game? Sure! Let’s see how to do so. In this game, the player can move around a map and pick up or drop items. The map and the items are represented as simple Python data structures.

Here’s the complete code for the game:

class Room:
def __init__(self, description, north=None, south=None, east=None, west=None):
self.description = description
self.north = north
self.south = south
self.east = east
self.west = west
self.items = []

class Player:
def __init__(self):
self.inventory = []

# Define the rooms
room1 = Room("You are in room 1. There is a room to the north.")
room2 = Room("You are in room 2. There is a room to the south.", south=room1)
room1.north = room2

# Place an item in room 1
room1.items.append("sword")

# Initialize the player
player = Player()

# Start the player in room 1
current_room = room1

while True:
command = input("\nWhat are you doing next? ").split()

match command:
case ["quit"]:
print("Goodbye!")
break
case ["look"]:
print(current_room.description)
if current_room.items:
print("You see: " + ", ".join(current_room.items))
else:
print("The room is empty.")
case ["get", item]:
if item in current_room.items:
player.inventory.append(item)

current_room.items.remove(item)
print(f"You picked up {item}.")
else:
print(f"There is no {item} here.")
case ["drop", item]:
if item in player.inventory:
player.inventory.remove(item)
current_room.items.append(item)
print(f"You dropped {item}.")
else:
print(f"You don't have {item}.")
case ["inventory"]:
if player.inventory:
print("You have: " + ", ".join(player.inventory))
else:
print("You are empty-handed.")
case ["go", direction]:
next_room = getattr(current_room, direction, None)
if next_room is not None:
current_room = next_room
else:
print(f"You can't go {direction} from here.")
case _:
print(f"Sorry, I couldn't understand '{' '.join(command)}'")

In this game, the player starts in room1, which contains a sword. The player can move between rooms by typing go followed by a direction (north, south, east, or west). The player can pick up an item from the current room by typing get followed by the item's name, and drop an item from their inventory by typing drop followed by the item's name. The player can also look around the room to see its description and any items in it and check their inventory to see the items they are carrying.

The game loop uses a match statement to interpret the player's commands: each case block handles a different command, performing the appropriate action and printing a message. The match statement's flexibility allows it to handle commands of different lengths and structures, making it a good fit for this kind of text parsing task.

This is a simple example, but it shows the potential of structural pattern matching for building more complex and flexible data processing logic. While learning a new language feature, it’s a good idea to experiment with it in different contexts and see how it can help you write clearer and more efficient code.

Join Medium Membership

If you enjoyed this article and want to keep learning more about this topic, I invite you to join Medium membership at this link.

By becoming a member, you’ll have access to a wider variety of high-quality content, and exclusive access to member-only stories, and you’ll be supporting independent writers and creators like myself. Plus, as a member, you’ll be able to highlight your favourite passages, save stories for later, and get personalized reading recommendations. Sign up today and let’s continue exploring this topic and others together.

Thank you for your support! Until next,

Marco

--

--

Marco Sanguineti

Graduated in Mechanical Engineering, I work in the world of AI, Deep Learning and Software Development. Passionate about Technology, Videogames and AI.