Raymond Hettinger
Raymond Hettinger

Reputation: 226231

How to express hasattr() duck typing logic with structural pattern matching?

I have code that checks for named tuples and dataclasses by looking for a _fields attribute:

if hasattr(candidate, '_fields'):
    do_action()

How can I express this with Python 3.10's match/case structural pattern matching?

Upvotes: 7

Views: 645

Answers (1)

Raymond Hettinger
Raymond Hettinger

Reputation: 226231

Understanding the documentation

PEP 634 for structural pattern matching documents this capability as a class pattern:

  • Writing cls() will do an isinstance() test.
  • Adding a keyword pattern cls(attr=variable) tests for the presence of an attribute and binds the value to the variable.

To emulate a hasattr() for duck typing:

  • Set cls to object so that any class can match.
  • Set attr to _fields, the attribute that must be present.
  • Set variable to _ if you don't need to capture the value or to some other variable name if you do want to capture the value.

This specific example

Your specific example, if hasattr(candidate, '_fields'): do_action(), translates to:

match candidate:
   case object(_fields=_):
       do_action()

Complete worked-out example

This shows how all the parts fit together:

from typing import NamedTuple
from dataclasses import dataclass

class Whale(NamedTuple):
    name: str
    num_fins: int

@dataclass
class Vehicle:
    name: str
    num_wheels: int

subject = Vehicle('bicycle', 2)
    
match subject:
    case object(num_fins=n):
        print(f'Found {n} fins')
    case object(num_wheels=_):
        print(f'Found wheeled object')
    case _:
        print('Unknown')

This script outputs:

Found wheeled object

Upvotes: 8

Related Questions