Pattern Matching

Ekkart Kleinod  • 

Hier in die Doku schauen, wie _, * und ** noch zum Vorteil eingesetzt werden können

Einfaches Matching

def handle_command(self, message):
    match message:
        case ['BEEPER', frequency, times]:
            self.beep(times, frequency)
        case ['NECK', angle]:
            self.rotate_neck(angle)
        case ['LED', ident, intensity]:
            self.leds[ident].set_brightness(ident, intensity)
        case ['LED', ident, red, green, blue]:
            self.leds[ident].set_color(ident, red, green, blue)
        case _:
            raise InvalidCommand(message)

Matching mit _

metro_areas = [
    ('Tokyo', 'JP', 36.933, (35.689722, 139.691667)),
    ('Delhi NCR', 'IN', 21.935, (28.613889, 77.208889)),
    ('Mexico City', 'MX', 20.142, (19.433333, -99.133333)),
    ('New York-Newark', 'US', 20.104, (40.808611, -74.020386)),
    ('São Paulo', 'BR', 19.649, (-23.547778, -46.635833)),
]
print(f'{"":15} | {"latitude":>9} | {"longitude":>9}')
for record in metro_areas:
    match record:
        case [name, _, _, (lat, lon)] if lon <= 0:
                print(f'{name:15} | {lat:9.4f} | {lon:9.4f}')
                |  latitude | longitude
Mexico City     |   19.4333 |  -99.1333
New York-Newark |   40.8086 |  -74.0204
São Paulo       |  -23.5478 |  -46.6358

Matching mit Mappings

from collections import OrderedDict
def get_creators(record: dict) -> list:
    match record:
        case {'type': 'book', 'api': 2, 'authors': [*names]}:
            return names
        case {'type': 'book', 'api': 1, 'author': name}:
            return [name]
        case {'type': 'book'}:
            raise ValueError(f"Invalid 'book' record: {record!r}")
        case {'type': 'movie', 'director': name}:
            return [name]
        case _:
            raise ValueError(f'Invalid record: {record!r}')
print(get_creators(dict(api=1, author='Douglas Hofstadter', type='book', title='Gödel, Escher, Bach')))
print(get_creators(OrderedDict(api=2, type='book', title='Python in a Nutshell', authors='Martelli Ravenscroft Holden'.split())))
print(get_creators({'type': 'book', 'pages': 770}))
print(get_creators('Spam, spam, spam'))
['Douglas Hofstadter']
['Martelli', 'Ravenscroft', 'Holden']
ValueError: Invalid 'book' record: {'type': 'book', 'pages': 770}
ValueError: Invalid record: 'Spam, spam, spam'

Matching mit Rest-Capture

creator = dict(author='Douglas Hofstadter', type='book', title='Gödel, Escher, Bach')
match creator:
        case {'type': 'book', **details}:
            print(f"Book details: {details}")
Book details: {'author': 'Douglas Hofstadter', 'title': 'Gödel, Escher, Bach'}