如何根据输入参数数量调度至不同的类方法?
Python实现类内同名多参数方法的多分派方案
需求说明
我们需要创建一个类,其中包含两个同名方法:
- 一个方法仅接受1个参数
- 另一个方法接受2个或更多参数
可以通过以下几种方式实现多分派(multi-dispatching):
方式一:使用第三方库multipledispatch
multipledispatch是专门用于实现多分派的工具库,用法直接直观:
先安装库:
pip install multipledispatch
实现代码:
from multipledispatch import dispatch class K: @dispatch(object) def method(self, one_arg): return f"处理1个参数:{one_arg}" @dispatch(object, object) def method(self, one_arg, two_args): return f"处理2个参数:{one_arg}, {two_args}" @dispatch(object, object, object) def method(self, one_arg, two_args, *args): return f"处理多个参数:{one_arg}, {two_args}, {args}" # 测试实例 k = K() print(k.method("a")) # 输出:处理1个参数:a print(k.method("a", "b")) # 输出:处理2个参数:a, b print(k.method("a", "b", "c", "d")) # 输出:处理多个参数:a, b, ('c', 'd')
方式二:自定义柯里化装饰器实现
通过自定义装饰器,根据传入参数的数量分发到对应处理函数:
class DispatchDecorator: def __init__(self): self.registry = {} def __call__(self, func): self.registry[0] = func return self def register(self, func): # 按函数参数数量注册 param_count = func.__code__.co_argcount self.registry[param_count] = func return self def __get__(self, instance, owner): # 绑定类实例,实现参数分发 def wrapper(*args): arg_count = len(args) if arg_count in self.registry: return self.registry[arg_count](instance, *args) raise TypeError(f"没有匹配参数数量为{arg_count}的方法") return wrapper class K: @DispatchDecorator() def method(self): pass # 基础入口,无实际功能 @method.register def method_of_one(self, one_arg): return f"处理1个参数:{one_arg}" @method.register def method_of_two(self, one_arg, two_args): return f"处理2个参数:{one_arg}, {two_args}" @method.register def method_of_multi(self, one_arg, two_args, three_args): return f"处理3个参数:{one_arg}, {two_args}, {three_args}" # 测试实例 k = K() print(k.method("x")) # 输出:处理1个参数:x print(k.method("x", "y")) # 输出:处理2个参数:x, y print(k.method("x", "y", "z")) # 输出:处理3个参数:x, y, z
方式三:结合functools.singledispatch与柯里化
functools.singledispatch默认基于参数类型分派,我们可以把参数数量转换成“类型标记”,实现按参数数量的分派逻辑:
from functools import singledispatch def arg_count_dispatch(func): dispatcher = singledispatch(func) def register(count): def decorator(f): dispatcher.register(type(count))(lambda self, *args: f(self, *args)) return f return decorator def wrapper(self, *args): return dispatcher(len(args))(self, *args) wrapper.register = register return wrapper class K: @arg_count_dispatch def method(self, *args): raise TypeError("没有匹配的参数数量") @method.register(1) def method_of_one(self, one_arg): return f"处理1个参数:{one_arg}" @method.register(2) def method_of_two(self, one_arg, two_args): return f"处理2个参数:{one_arg}, {two_args}" @method.register(3) def method_of_multi(self, one_arg, two_args, three_args): return f"处理3个参数:{one_arg}, {two_args}, {three_args}" # 测试实例 k = K() print(k.method("foo")) # 输出:处理1个参数:foo print(k.method("foo", "bar")) # 输出:处理2个参数:foo, bar print(k.method("foo", "bar", "baz")) # 输出:处理3个参数:foo, bar, baz
内容的提问来源于stack exchange,提问作者Toothpick Anemone
相关产品推荐
相关产品推荐

