Crimes with Python's Pattern Matching (2022)
Python 3.10 добавил сопоставление с образцом, которое использует isinstance
.
ABC с __subclasshook__
могут подменять проверку типа, поэтому:
class NotIterable(ABC):
@classmethod
def __subclasshook__(cls, C):
return not hasattr(C, "__iter__")
match x:
case NotIterable(): ...
работает — 10
считается NotIterable
, строки и списки — нет.
Аналогично можно «матчить» по наличию атрибутов:
class DistanceMetric(ABC):
@classmethod
def __subclasshook__(cls, C):
return hasattr(C, "distance")
и деструктурировать:
match x:
case DistanceMetric(distance=d): ...
Динамически создаём комбинаторы:
def Not(cls):
class _Not(ABC):
@classmethod
def __subclasshook__(_, C):
return not issubclass(C, cls)
return _Not
n = Not(DistanceMetric)
match x:
case n(): ...
Синтаксис не позволяет писать Not(DistanceMetric)()
прямо в case
, но сохранив сгенерированный ABC в переменную, обходим ограничение.