Python的3.4 added的能力来定义函数的静态方法重载。这实质上是从文档的例子:
from functools import singledispatch
class TestClass(object):
@singledispatch
def test_method(arg, verbose=False):
if verbose:
print("Let me just say,", end=" ")
print(arg)
@test_method.register(int)
def _(arg):
print("Strength in numbers, eh?", end=" ")
print(arg)
@test_method.register(list)
def _(arg):
print("Enumerate this:")
for i, elem in enumerate(arg):
print(i, elem)
if __name__ == '__main__':
TestClass.test_method(55555)
TestClass.test_method([33, 22, 11])
在其最纯粹的形式中,singledispatch
实现依赖于第一个参数,以确定类型,因此使它棘手此功能扩展到实例方法。
有没有人有如何使用(或杰里 - 钻机)此功能让它与实例方法的工作有什么建议?
更新:对于Python 3.8,
functools.singledispatchmethod
将允许在方法,classmethods,abstractmethods和staticmethods单牒。对于老版本的Python,看到这个答案的其余部分。
纵观source为singledispatch
,我们可以看到,装饰返回功能wrapper()
,它选择的功能,从那些基于args[0]
的类型注册打电话......
def wrapper(*args, **kw):
return dispatch(args[0].__class__)(*args, **kw)
......这是罚款,一个普通的功能,而不是一个实例方法,它的第一个参数多大用处总是将是self
。
我们可以,但是,写一个新的装饰methdispatch
,依靠qazxswpoi做繁重,而是返回选择哪个注册函数来调用基于singledispatch
的类型的包装功能:
args[1]
下面是使用Decorator的一个简单的例子:
from functools import singledispatch, update_wrapper
def methdispatch(func):
dispatcher = singledispatch(func)
def wrapper(*args, **kw):
return dispatcher.dispatch(args[1].__class__)(*args, **kw)
wrapper.register = dispatcher.register
update_wrapper(wrapper, func)
return wrapper
请注意,两个装饰class Patchwork(object):
def __init__(self, **kwargs):
for k, v in kwargs.items():
setattr(self, k, v)
@methdispatch
def get(self, arg):
return getattr(self, arg, None)
@get.register(list)
def _(self, arg):
return [self.get(x) for x in arg]
方法和注册到get()
该方法具有初始list
参数如常。
测试self
类:
Patchwork
装饰器本质上是一个包装,是以包装的函数作为参数并返回另一个功能。
作为接受的答案说,>>> pw = Patchwork(a=1, b=2, c=3)
>>> pw.get("b")
2
>>> pw.get(["a", "c"])
[1, 3]
返回singledispatch
,是以第一个参数是注册类型 - wrapper
的实例方法。
作为这个问题的答案所示,在这样的情况下,你可以写其他包装猴子修补装饰。但这种哈克修复并不总是最好的选择。
正如像任何其他功能,您可以拨打包装,并明确地传递参数给它,这似乎更简单,扁平化,更具可读性,我如果这种方法的重载只在很少的包装制作。
self
还有另外一个模块,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
,允许多方法。
除了singledispatch
对象,与Dispatcher
兼容构造结,它提供了一个singledispatch
装饰,其对用户隐藏这些对象的创建和操纵。
调度装饰使用函数的名称来选择合适的调度对象,它增加了新的签名/功能。当它遇到一个新的功能将其命名为创建一个新的Dispatcher对象和商店名称/调度以供将来参考命名空间对。
例如:
dispatch