prefer-match-type-dispatch
Prefer match for structural runtime type dispatch.
Why
A repeated mutually exclusive isinstance dispatch repeats its subject and hides the closed list of runtime shapes. Class patterns make the alternatives explicit without repeating the dispatch subject.
Fix
Replace the branches with match subject and one class-pattern arm per distinct type; combine types that share behavior with an OR-pattern.
Examples
import ast
def has_binding(node, name): if isinstance(node, ast.ListComp): return True if isinstance(node, ast.FunctionDef): if name in bindings(node): return True elif isinstance(node, ast.ClassDef): if name in bindings(node): return True return Falseimport ast
def has_binding(node, name): match node: case ast.ListComp(): return True case ast.FunctionDef(): if name in bindings(node): return True case ast.ClassDef(): if name in bindings(node): return True return Falsedef parse(value: object): if isinstance(value, str): return parse_text(value) elif isinstance(value, bytes): return parse_bytes(value) elif isinstance(value, dict): return parse_mapping(value) raise TypeError(type(value))def parse(value: object): match value: case str(): return parse_text(value) case bytes(): return parse_bytes(value) case dict(): return parse_mapping(value) case _: raise TypeError(type(value))def is_text(value): if isinstance(value, str) or isinstance(value, bytes): return True return Falsedef is_text(value): match value: case str() | bytes(): return True return Falsefrom pydantic import BaseModel
class Session(BaseModel): allowed: bool
def authorize(subject): if isinstance(subject, Session): if not subject.allowed: raise PermissionErrorfrom pydantic import BaseModel
class Session(BaseModel): allowed: bool
def authorize(subject): match subject: case Session(): if not subject.allowed: raise PermissionError case _: returnimport ast
def dotted_tail(node: ast.expr) -> str | None: if isinstance(node, ast.Name): return node.id if isinstance(node, ast.Attribute): return node.attr return Noneimport ast
def dotted_tail(node: ast.expr) -> str | None: match node: case ast.Name(): return node.id case ast.Attribute(): return node.attr case _: return Nonedef label(value): if isinstance(value, str): return "text" elif isinstance(value, bytes): return "binary" return "other"def label(value): match value: case str(): return "text" case bytes(): return "binary" return "other"