装饰器 · singledispatch

0. 一句话定位

维度 内容
作用对象 函数
使用场景 多态分发
来源 标准库 functools.singledispatch
语法形式 @singledispatch + @func.register(type)

1. 做什么

根据第一个参数的运行时类型选择注册实现;无匹配时走默认(被 @singledispatch 装饰的函数体)。

2. 重点参数

参数 类型 默认值 作用 配置建议
func callable 默认实现 作为 @singledispatch 的直接目标
type type / callable 注册分支 @f.register(int)@f.register 装饰下一函数

singledispatchmethod(3.8+)用于类方法的第一参数为 self 之外的分派,另见标准库文档。

3. 最小可运行示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from functools import singledispatch

@singledispatch
def display_info(arg):
print(f"Generic: {arg}")

@display_info.register(int)
def _(arg):
print(f"Received an integer: {arg}")

@display_info.register(float)
def _(arg):
print(f"Received a float: {arg}")

@display_info.register(str)
def _(arg):
print(f"Received a string: {arg}")

@display_info.register(list)
def _(arg):
print(f"Received a sequence: {arg}")

display_info(39)
display_info(3.19)
display_info("Hello World!")
display_info([2, 4, 6])
1
2
3
4
Received an integer: 39
Received a float: 3.19
Received a string: Hello World!
Received a sequence: [2, 4, 6]

4. 常见变体

注册抽象基类

1
2
3
4
5
from collections.abc import Sequence

@display_info.register(Sequence)
def _(arg):
print(f"Sequence: {len(arg)} items")

查看已注册类型display_info.registry

5. 适用 / 不适用

适用

  • 同一操作名对不同输入类型有不同逻辑(序列化、格式化、相等比较)
  • 避免长链 isinstance

不适用

  • 多分派(多个参数类型组合)→ 需 multipledispatch 等第三方库
  • 子类优先级:更具体类型应后注册或显式注册,避免被 ABC 抢先

6. 易踩坑

  • 只分派第一个参数;其余参数不参与选择
  • 默认实现应处理未知类型或明确抛错
  • 注册函数名可任意(常用 _),不影响分派

7. 近邻替代

替代 何时用
isinstance 分支 分支少、无扩展需求
multipledispatch 多参数类型组合分派

8. 参考

-------------本文结束感谢您的阅读-------------