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

Functools -- singledispatchmethod

✅ 1. singledispatchmethod 是什么?

它是 singledispatch 的 类方法版本。

from functools import singledispatchmethod

功能:

  • 根据“方法第一个参数的类型(除 self 外)”自动分发到不同方法
  • 实现“面向对象版函数重载”
  • 让类的方法根据输入类型自动选择实现

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

from functools import singledispatchmethod

class Processor:

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

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

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

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

输出:

处理整数:10
处理字符串:abc

👉 根据 value 的类型自动选择不同方法。

🟦 3. 使用场景(非常常用)

3.1 根据“数据类型”选择不同处理流程(最常用)

你有:

  • dict
  • list
  • str
  • bytes
  • pandas.DataFrame
  • pydantic.BaseModel

函数可以自动分发到对应处理逻辑。

3.2 API 输入格式多种多样(FastAPI / CLI 最适用)

一个类处理多种数据:

p.process(str_data)
p.process(json_dict)
p.process(pandas_dataframe)

非常适合你做的数据同步、股票数据处理框架。

3.3 插件系统(可以第三方扩展)

不同的模块可以注册新的类型处理器:

@processor.process.register
def _(self, value: MyCustomType):
    ...

无需修改主类。

3.4 复杂的逻辑拆分(替代 if/elif/else)

避免几十行的:

if isinstance(x, dict):
elif isinstance(x, list):
elif isinstance(x, str):
...

使用 singledispatchmethod 更优雅。

🟩 4. 例子:多格式的数据加载器

class Loader:

    @singledispatchmethod
    def load(self, data):
        raise TypeError("不支持的类型")

    @load.register
    def _(self, data: str):
        return f"加载字符串: {data}"

    @load.register
    def _(self, data: list):
        return f"加载列表: {data}"

    @load.register
    def _(self, data: dict):
        return f"加载字典: {data}"

🟧 5. 使用类型注册(不写类型注解)

class Handler:
    @singledispatchmethod
    def handle(self, value):
        ...

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

适合动态场景。

🟥 6. 注意:只根据“第一个非 self 参数”分发

例如:

def process(self, a, b):

分发只看 a,不看 b。

🟩 7. 支持继承链查找(非常强大)

class Animal: pass
class Dog(Animal): pass

class P:
    @singledispatchmethod
    def speak(self, x):
        ...

    @speak.register
    def _(self, x: Animal):
        print("Animal speak")

p = P()
p.speak(Dog())   # Dog 自动匹配父类 Animal

🟦 8. 与 match-case 的对比

功能 singledispatchmethod match-case
按类型分发
类方法
插件扩展
使用继承链
可集中管理逻辑
扩展性 ⭐⭐⭐⭐⭐ ⭐⭐

singledispatchmethod 更适合大型项目和扩展性要求高的系统。

🟪 9. 实战:股票数据解析器(你能直接用)

class StockParser:

    @singledispatchmethod
    def parse(self, data):
        raise TypeError("不支持的数据类型")

    @parse.register
    def _(self, data: dict):
        return f"解析 dict: {data['code']}"

    @parse.register
    def _(self, data: str):
        return f"解析 JSON 字符串: {data}"

    @parse.register
    def _(self, data: list):
        return [self.parse(item) for item in data]

用法:

parser = StockParser()
parser.parse({"code": "600000"})
parser.parse('[{"code": "600000"}]')
parser.parse([{"code": "002594"}, {"code": "600519"}])

🟦 10. 在 FastAPI 中封装万能参数处理器

class ParamParser:
    @singledispatchmethod
    def normalize(self, v):
        return v

    @normalize.register
    def _(self, v: str):
        return v.strip()

    @normalize.register
    def _(self, v: list):
        return [self.normalize(i) for i in v]

⭐ 11. 一屏速查表(终极总结)

from functools import singledispatchmethod

class C:
    @singledispatchmethod
    def method(self, x): ...

    @method.register
    def _(self, x: int): ...

    @method.register
    def _(self, x: str): ...

特点:

  • 类方法自动“按类型分发”
  • 扩展性强,可插件式开发
  • 替代大量 if-else
  • 首个非-self 参数决定分发
  • 支持继承链查找