# 类型分发与functools.singledispatch # 5.1 singledispatch的基本概念: # 尽管Python没有内置的函数重载,但标准库中的functools.singledispatch装饰器提供了一种实现单分派泛型函数(single-dispatch generic function)的机制。这意味着同一个函数名可以根据其第一个参数的类型来调用不同的实现。这在一定程度上模拟了基于类型的函数重载。 # 5.2 什么是单分派?如何用来实现“伪重载”? # 单分派(single-dispatch)是一种“根据第一个参数的类型来自动选择函数实现”的机制,类似于其他语言中的“基于类型的函数重载”。 # 在Python中,可以借助functools.singledispatch装饰器,让同一个函数名有多个实现,具体调用哪个实现由第一个参数的类型自动决定。 # 单分派的核心特点: # “重载”仅对第一个参数生效(后面的参数类型不会影响分派)。 # 每个实现用.register(类型)方式绑定到主函数。 # 如果没有匹配的类型,就会走“默认实现”。 # 本质上这是一种“类型分发”(Type Dispatch)机制,而不是传统意义上的多参数重载。 # 适用场景举例: # 序列化/反序列化不同类型数据 # 数据处理框架按输入类型走不同逻辑 # 实现API或工具函数对各类对象采用差异化策略 # 实际开发中,@singledispatch 不仅可以用来简化对不同类型参数的分支判断,还可以根据需求扩展更加复杂的类型分发逻辑。 # 假设我们要实现一个serialize_data函数,根据参数的数据类型不同,对其进行不同方式的序列化。我们可以为常见的类型——如str、int、float、list、dict等——分别注册对应的序列化方法,这样无需编写冗长的if-elif-else判断。遇到未注册的新类型时,自动调用默认序列化逻辑。 # 这种方式不仅让代码更优雅,可维护性增强,而且易于扩展和复用:后续只需新增注册实现即可轻松支持新的类型处 from functools import singledispatch @singledispatch def serialize_data(data): return str(data) # 根据字典类型类型注册序列化方法 @serialize_data.register(dict) def _(data): result = [] for key, val in data.items(): result.append(f"{key}:{val}") return "{" + ",".join(result) + "}" # 根据列表注册序列化方法 @serialize_data.register(list) def _(data): return "[" + ",".join(map(str, data)) + "]" @serialize_data.register(str) def _(data): return f"{data}" @serialize_data.register(int) def _(data): return f"整数{data}" @serialize_data.register(float) def _(data): return f"浮点数{data}" dict_data = {"name": "Alice", "age": 30} print(f"字典序列化: {serialize_data(dict_data)}") list_data = [1, 2, 3, 4, 5] print(f"列表序列化: {serialize_data(list_data)}") # 输出: 列表序列化: [1, 2, 3, 4, 5] # 序列化字符串 str_data = "Hello World" print(f"字符串序列化: {serialize_data(str_data)}") # 输出: 字符串序列化: "Hello World" # # 序列化整数 int_data = 42 print(f"整数序列化: {serialize_data(int_data)}") # 输出: 整数序列化: 整数: 42 # 序列化浮点数 float_data = 3.14159 print(f"浮点数序列化: {serialize_data(float_data)}") # # 输出: 浮点数序列化: 浮点数: 3.14 # # 序列化其他类型(使用默认方法) bool_data = True print(f"布尔值序列化: {serialize_data(bool_data)}")