当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


Python functools.singledispatch用法及代码示例


用法:

@functools.singledispatch

将函数转换为 single-dispatch 通用函数。

要定义泛型函数,请使用 @singledispatch 装饰器对其进行装饰。使用 @singledispatch 定义函数时,请注意调度发生在第一个参数的类型上:

>>> from functools import singledispatch
>>> @singledispatch
... def fun(arg, verbose=False):
...     if verbose:
...         print("Let me just say,", end=" ")
...     print(arg)

要向函数添加重载实现,请使用泛型函数的register() 属性,该属性可用作装饰器。对于带有类型注释的函数,装饰器将自动推断第一个参数的类型:

>>> @fun.register
... def _(arg: int, verbose=False):
...     if verbose:
...         print("Strength in numbers, eh?", end=" ")
...     print(arg)
...
>>> @fun.register
... def _(arg: list, verbose=False):
...     if verbose:
...         print("Enumerate this:")
...     for i, elem in enumerate(arg):
...         print(i, elem)

对于不使用类型注释的代码,可以将适当的类型参数显式传递给装饰器本身:

>>> @fun.register(complex)
... def _(arg, verbose=False):
...     if verbose:
...         print("Better than complicated.", end=" ")
...     print(arg.real, arg.imag)
...

要启用注册 lambdas 和预先存在的函数,register() 属性也可以以函数形式使用:

>>> def nothing(arg, verbose=False):
...     print("Nothing.")
...
>>> fun.register(type(None), nothing)

register() 属性返回未修饰的函数。这启用了装饰器堆叠 pickling 以及为每个变体独立创建单元测试:

>>> @fun.register(float)
... @fun.register(Decimal)
... def fun_num(arg, verbose=False):
...     if verbose:
...         print("Half of your number:", end=" ")
...     print(arg / 2)
...
>>> fun_num is fun
False

调用时,泛型函数会根据第一个参数的类型分派:

>>> fun("Hello, world.")
Hello, world.
>>> fun("test.", verbose=True)
Let me just say, test.
>>> fun(42, verbose=True)
Strength in numbers, eh? 42
>>> fun(['spam', 'spam', 'eggs', 'spam'], verbose=True)
Enumerate this:
0 spam
1 spam
2 eggs
3 spam
>>> fun(None)
Nothing.
>>> fun(1.23)
0.615

如果特定类型没有注册实现,则使用其方法解析顺序来查找更通用的实现。用@singledispatch 修饰的原始函数注册为基本object 类型,这意味着如果找不到更好的实现,则使用它。

如果实现注册到抽象基类,则基类的虚拟子类将被分派到该实现:

>>> from collections.abc import Mapping
>>> @fun.register
... def _(arg: Mapping, verbose=False):
...     if verbose:
...         print("Keys & Values")
...     for key, value in arg.items():
...         print(key, "=>", value)
...
>>> fun({"a": "b"})
a => b

要检查泛型函数将为给定类型选择哪个实现,请使用 dispatch() 属性:

>>> fun.dispatch(float)
<function fun_num at 0x1035a2840>
>>> fun.dispatch(dict)    # note: default implementation
<function fun at 0x103fe0000>

要访问所有已注册的实现,请使用只读 registry 属性:

>>> fun.registry.keys()
dict_keys([<class 'NoneType'>, <class 'int'>, <class 'object'>,
          <class 'decimal.Decimal'>, <class 'list'>,
          <class 'float'>])
>>> fun.registry[float]
<function fun_num at 0x1035a2840>
>>> fun.registry[object]
<function fun at 0x103fe0000>

3.4 版中的新函数。

在 3.7 版中更改: register()属性现在支持使用类型注释。

相关用法


注:本文由纯净天空筛选整理自python.org大神的英文原创作品 functools.singledispatch。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。