Skip to main content
Documents
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

Functools -- singledispatch

✅ 1. singledispatch 是什么?

Python 不支持函数重载(同名函数不同参数类型)。

但 functools.singledispatch 让你可以按照“参数类型”自动分发到不同函数。

  • 类似 Java/C++ 的函数重载
  • 但基于“参数类型”进行分发
  • 扩展性非常强(特别适合插件系统)

用法:

from functools import singledispatch

🟦 2. 最小示例(立刻理解)

from functools import singledispatch

@singledispatch
def process(value):
    raise NotImplementedError(f"不支持类型: {type(value)}")

@process.register
def _(value: int):
    return f"整数:{value}"

@process.register
def _(value: str):
    return f"字符串:{value}"

print(process(10))
print(process("hello"))

输出:

整数:10
字符串:hello

👉 同一个函数名 process,根据第一个参数类型自动调用不同函数

🟩 3. 使用场景(非常重要)

1. 不同输入类型需要不同处理逻辑(最常用)

  • dict / list / str / int 需要不同解析方式
  • JSON 转换
  • 数据格式化
  • 根据股票数据不同格式做不同处理

2. 封装通用接口(你可以直接在项目中使用)

process(obj)

调用者无需关注 obj 的类型。

3. 框架 / 插件式设计(非常强大)

不同模块可以使用:

@process.register

来扩展功能,而不需要修改主函数。

🟦 4. 复杂示例:序列化器(serializer)

@singledispatch
def serialize(obj):
    raise TypeError(f"不能序列化类型:{type(obj)}")

@serialize.register
def _(obj: int):
    return str(obj)

@serialize.register
def _(obj: str):
    return obj

@serialize.register
def _(obj: list):
    return "[" + ", ".join(serialize(i)) + "]"

@serialize.register
def _(obj: dict):
    return "{" + ", ".join(f"{k}: {serialize(v)}" for k, v in obj.items()) + "}"

🟧 5. 使用 type 注册(关键技巧)

@process.register(int)
def _(value):
    return f"int: {value}"

适合无法注解类型的场景。

🟦 6. 默认函数使用 “fallback”(兜底处理)

@singledispatch
def handle(x):
    print("默认处理: ", x)

如果没有匹配类型,会调用默认函数。

🟧 7. 子类继承行为

class Animal: ...
class Dog(Animal): ...

@handle.register(Animal)
def _(x):
    print("动物")

print(handle(Dog()))

输出:

动物

👉 如果类型未注册,会向上查找父类类型。

🟥 8. 仅根据第 1 个参数分发(限制)

singledispatch 只看第一个参数类型。

如果你想基于多个参数类型分发,需要:

  • singledispatchmethod
  • 或第三方库 multimethod / multipledispatch

🟦 9. Python 3.8+ 的 singledispatchmethod(方法版)

用于类的方法:

from functools import singledispatchmethod

class Processor:
    @singledispatchmethod
    def process(self, value):
        raise NotImplementedError()

    @process.register
    def _(self, value: int):
        return f"int: {value}"

    @process.register
    def _(self, value: str):
        return f"str: {value}"

p = Processor()
print(p.process(10))
print(p.process("abc"))

🟪 10. 和 match-case 对比

功能 singledispatch match-case
基于类型分发
可扩展性强
插件式扩展
支持复杂逻辑
适合框架

singledispatch 更适合构建扩展性的系统。

🟦 11. 性能注意事项

第一次调用某类型会进行注册和缓存

后续调用是 O(1) 查找,非常快。

🟩 12. 一屏速查表(终极总结)

from functools import singledispatch

@singledispatch
def func(x): ...

@func.register
def _(x: int): ...

@func.register
def _(x: str): ...

func(10)       # 调用 int 版
func("hello")  # 调用 str 版

特点:

  • 按类型自动分发
  • 可扩展
  • 插件式设计最佳
  • 仅根据第一个参数决定
  • 支持继承链查找
  • 支持方法版:singledispatchmethod