装饰器本质上是一个包装器,它将被包装的函数作为参数并返回另一个函数。
如接受的答案中所述,singledispatch
返回wrapper
将第一个参数作为注册类型的 a -self
在实例方法中。
如该答案所示,在这种情况下,您可以编写另一个包装器来猴子修补装饰器。但这种 hacky 修复并不总是最好的选择。
与任何其他函数一样,您可以调用包装器并将参数显式传递给它,如果这种方法重载很少在包中进行,这对我来说似乎更简单、更扁平且更具可读性。
from functools import singledispatch
class TestClass(object):
def __init__(self):
self.test_method = singledispatch(self.test_method)
self.test_method.register(int, self._test_method_int)
self.test_method.register(list, self._test_method_list)
def test_method(self, arg, verbose=False):
if verbose:
print("Let me just say,", end=" ")
print(arg)
def _test_method_int(self, arg):
print("Strength in numbers, eh?", end=" ")
print(arg)
def _test_method_list(self, arg):
print("Enumerate this:")
for i, elem in enumerate(arg):
print(i, elem)
if __name__ == '__main__':
test = TestClass()
test.test_method(55555)
test.test_method([33, 22, 11])
还有另一个模块multipledispatch
(不是标准的,但包含在 Anaconda 中并且没有任何非标准依赖项),正如名称已经表明的那样singledispatch
,与 不同的是,它允许多方法。
除了Dispatcher
对象之外,使用singledispatch
-compatible 语法,它还提供了一个dispatch
装饰器,对用户隐藏这些对象的创建和操作。
调度装饰器使用函数的名称来选择合适的 Dispatcher 对象,向其添加新的签名/函数。当它遇到新的函数名称时,它会创建一个新的 Dispatcher 对象并将名称/Dispatcher 对存储在命名空间中以供将来参考。
例如:
from types import LambdaType
from multipledispatch import dispatch
class TestClass(object):
@dispatch(object)
def test_method(self, arg, verbose=False):
if verbose:
print("Let me just say,", end=" ")
print(arg)
@dispatch(int, float)
def test_method(self, arg, arg2):
print("Strength in numbers, eh?", end=" ")
print(arg + arg2)
@dispatch((list, tuple), LambdaType, type)
def test_method(self, arg, arg2, arg3):
print("Enumerate this:")
for i, elem in enumerate(arg):
print(i, arg3(arg2(elem)))
if __name__ == '__main__':
test = TestClass()
test.test_method(55555, 9.5)
test.test_method([33, 22, 11], lambda x: x*2, float)