Tech News
← Back to articles

Crimes with Python's Pattern Matching (2022)

read original related products more articles

One of my favorite little bits of python is __subclasshook__ . Abstract Base Classes with __subclasshook__ can define what counts as a subclass of the ABC, even if the target doesn’t know about the ABC. For example:

class PalindromicName (ABC): @classmethod def __subclasshook__ (cls, C): name = C . __name__ . lower() return name[:: - 1 ] == name class Abba : ... class Baba : ... >>> isinstance(Abba(), PalindromicName) True >>> isinstance(Baba(), PalindromicName) False

You can do some weird stuff with this. Back in 2019 I used it to create non-monotonic types, where something counts as a NotIterable if it doesn’t have the __iter__ method. There wasn’t anything too diabolical you could do with this: nothing in Python really interacted with ABCs, limiting the damage you could do with production code.

Then Python 3.10 added pattern matching.

A quick overview of pattern matching

From the pattern matching tutorial:

match command . split(): case [ "quit" ]: print( "Goodbye!" ) quit_game() case [ "look" ]: current_room . describe() case [ "get" , obj]: character . get(obj, current_room)

You can match on arrays, dictionaries, and custom objects. To support matching objects, Python uses isinstance(obj, class) , which checks

If obj is of type class If obj is a transitive subtype of class If class is an ABC and defines a __subclasshook__ that matches the type of obj .

That made me wonder if ABCs could “hijack” a pattern match. Something like this:

... continue reading