6.9. Match Class — Python
A class pattern is similar to the above but matches attributes
instead of keys. It looks like datetime.date(year=y, day=d). It
matches instances of the given type, having at least the specified
attributes, as long as the attributes match with the corresponding
sub-patterns. It binds whatever the sub-patterns bind when matching
with the values of the given attributes. An optional protocol also
allows matching positional arguments.
6.9.1. Problem
>>> class User: ... pass >>> >>> class Staff: ... pass >>> >>> class Admin: ... pass >>> >>> >>> alice = User() >>> >>> if isinstance(alice, User): ... pass ... elif isinstance(alice, Staff): ... pass ... elif isinstance(alice, Admin): ... pass
6.9.2. Solution
>>> class User: ... pass >>> >>> class Staff: ... pass >>> >>> class Admin: ... pass >>> >>> >>> alice = User() >>> >>> match alice: ... case User(): pass ... case Staff(): pass ... case Admin(): pass
6.9.3. Match Args
Match Args with two attributes:
>>> class User: ... __match_args__ = ('firstname', 'lastname') ... ... def __init__(self, firstname, lastname): ... self.firstname = firstname ... self.lastname = lastname >>> >>> >>> alice = User('Alice', 'Apricot') >>> >>> match alice: ... case User('Alice', 'Apricot'): print('alice') ... case User('Bob', 'Blackthorn'): print('bob') ... case User('Carol', 'Corn'): print('carol') ... alice
Match Args with one attribute:
>>> class User: ... __match_args__ = ('firstname',) ... ... def __init__(self, firstname, lastname): ... self.firstname = firstname ... self.lastname = lastname >>> >>> >>> alice = User('Alice', 'Apricot') >>> >>> match alice: ... case User('Alice'): print('alice') ... case User('Bob'): print('bob') ... case User('Carol'): print('carol') ... alice
6.9.4. Does Not Create New Instances
>>> class User: ... __match_args__ = ('firstname', 'lastname') ... ... def __init__(self, firstname, lastname): ... print(f'Creating User: {firstname} {lastname}') ... self.firstname = firstname ... self.lastname = lastname >>> >>> >>> alice = User('Alice', 'Apricot') Creating User: Alice Apricot >>> >>> match alice: ... case User('Alice', 'Apricot'): print('alice') ... case User('Bob', 'Blackthorn'): print('bob') ... case User('Carol', 'Corn'): print('carol') ... alice
6.9.5. Match Other Fields
>>> class User: ... __match_args__ = ('email',) ... ... def __init__(self, firstname, lastname): ... self.firstname = firstname ... self.lastname = lastname ... self.email = f'{firstname.lower()}@example.com' >>> >>> >>> alice = User('Alice', 'Apricot') >>> >>> match alice: ... case User('alice@example.com'): print('alice') ... case User('bob@example.com'): print('bob') ... case User('carol@example.com'): print('carol') alice
6.9.6. Case Study
SetUp:
Using if:
>>> if isinstance(data, int): ... pass ... elif isinstance(data, float): ... pass ... elif isinstance(data, str): ... pass
Using match:
>>> match data: ... case int(): pass ... case float(): pass ... case str(): pass
6.9.7. Use Case - 1
>>> x = True >>> >>> match x: ... case bool(): print('Is a bool') ... case int(): print('Is an int') ... case float(): print('Is a float') ... Is a bool
6.9.8. Use Case - 2
>>> x = True >>> >>> match x: ... case int(): print('Is an int') ... case bool(): print('Is a bool') ... case float(): print('Is a float') ... Is an int
Is equivalent to:
>>> if isinstance(x, int): ... print('Is an int') ... elif isinstance(x, bool): ... print('Is a bool') ... elif isinstance(x, float): ... print('Is a float') ... Is an int
Because:
>>> isinstance(True, bool) True >>> >>> isinstance(True, int) True
Every bool inherits from int:
>>> bool.mro() [<class 'bool'>, <class 'int'>, <class 'object'>]
6.9.9. Use Case - 1
>>> from datetime import datetime >>> >>> obj = datetime(1969, 7, 21, 2, 56, 15) >>> obj datetime.datetime(1969, 7, 21, 2, 56, 15) >>> >>> match obj: ... case datetime(): print('Instance of a datetime class') ... case date(): print('Instance of a date class') ... case time(): print('Instance of a time class') ... case timedelta(): print('Instance of a timedelta class') ... Instance of a datetime class
6.9.10. Use Case - 2
>>> import json >>> from datetime import date, time, datetime, timezone >>> >>> >>> DATA = {'firstname': 'Alice', ... 'lastname': 'Apricot', ... 'birthdate': date(2000, 1, 1)} >>> >>> >>> def encoder(value): ... match value: ... case datetime() | date() | time(): ... return value.isoformat() ... case timedelta(): ... return value.total_seconds() >>> >>> >>> json.dumps(DATA, default=encoder) '{"firstname": "Alice", "lastname": "Apricot", "birthdate": "2000-01-01"}'
6.9.11. Use Case - 3
>>> import json >>> from datetime import date, time, datetime, timezone >>> from pprint import pprint >>> >>> >>> DATA = {'mission': 'Ares 3', ... 'launch_date': datetime(2035, 6, 29), ... 'destination': 'Mars', ... 'destination_landing': datetime(2035, 11, 7), ... 'destination_location': 'Acidalia Planitia', ... 'crew': [{'name': 'Melissa Lewis', 'birthdate': date(1995, 7, 15)}, ... {'name': 'Rick Martinez', 'birthdate': date(1996, 1, 21)}, ... {'name': 'Alex Vogel', 'birthdate': date(1994, 11, 15)}, ... {'name': 'Chris Beck', 'birthdate': date(1999, 8, 2)}, ... {'name': 'Beth Johanssen', 'birthdate': date(2006, 5, 9)}, ... {'name': 'Mark Watney', 'birthdate': date(1994, 10, 12)}]}
>>> json.dumps(DATA) Traceback (most recent call last): TypeError: Object of type datetime is not JSON serializable when serializing dict item 'launch_date'
>>> def encoder(obj): ... match obj: ... case datetime() | date() | time(): ... return obj.isoformat() ... case timedelta(): ... return obj.total_seconds() >>> >>> result = json.dumps(DATA, default=encoder, indent=2) >>> print(result) { "mission": "Ares 3", "launch_date": "2035-06-29T00:00:00", "destination": "Mars", "destination_landing": "2035-11-07T00:00:00", "destination_location": "Acidalia Planitia", "crew": [ { "name": "Melissa Lewis", "birthdate": "1995-07-15" }, { "name": "Rick Martinez", "birthdate": "1996-01-21" }, { "name": "Alex Vogel", "birthdate": "1994-11-15" }, { "name": "Chris Beck", "birthdate": "1999-08-02" }, { "name": "Beth Johanssen", "birthdate": "2006-05-09" }, { "name": "Mark Watney", "birthdate": "1994-10-12" } ] }