當前位置: 首頁>>代碼示例 >>用法及示例精選 >>正文


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。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。