Python 3.5 - 使用@overload重载方法

时间:2016-09-28 13:23:16

标签: python python-3.5 overloading

Python 3.5+有一个overloading包。 对于这个包,可以重新定义方法,但是使用不同的类型提示,它的装饰器会找出,应该调用哪个重载方法。

常见编码模式:

class foo:
  def func(param):
    if instance(param, int):
      pass
    elif instance(param, str):
      pass
    elif instance(param, list):
      pass
    else:
      raise ValueError()

使用@overload:

class foo:
  @overload
  def func(param: int):
    pass

  @overload
  def func(param: str):
    pass

  @overload
  def func(param: list):
    pass

这是documentation

我的问题是:

  • 与旧式参数类型切换相比,性能影响有多大?
  • 此包如何访问类型提示?

2 个答案:

答案 0 :(得分:2)

您必须使用真实代码自行衡量。

我快速查看了这个库的代码,结论很简单。它使用了大量的反射(检查包)和类型比较。自己的检查包主要由调试工具使用 - 它们总是会降低代码的速度。

看看以下几行:

complexity = complexity_mapping[id]
if complexity & 8 and isinstance(arg, tuple):
     element_type = tuple(type(el) for el in arg)
elif complexity & 4 and hasattr(arg, 'keys'):
     element_type = (type(element), type(arg[element]))
else:
     element_type = type(element)

type_hints = typing.get_type_hints(func) if typing else func.__annotations__
types = tuple(normalize_type(type_hints.get(param, AnyType)) for param in parameters)

请注意,此套餐超过7个月,只有70颗星。 Python不是Java ......你真的用这个软件包损害了python本身:D你最好实现一些核心api方法,根据类型参数将调用委托给其他方法/对象 - 就像应该这样用Python完成。

答案 1 :(得分:1)

从 python 3.4 开始,有一个核心 API 功能 functools.singledispatch,它允许您注册重载函数。

来自文档

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

>>> @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("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

注意:只输入第一个参数!

此外,还有(自 python 3.8 起)类方法调用 functools.singledispatchmethod 的等效装饰器