我试图在Python中实现方法重载:
class A:
def stackoverflow(self):
print 'first method'
def stackoverflow(self, i):
print 'second method', i
ob=A()
ob.stackoverflow(2)
但是输出是第二种方法2;类似的:
class A:
def stackoverflow(self):
print 'first method'
def stackoverflow(self, i):
print 'second method', i
ob=A()
ob.stackoverflow()
给了
Traceback (most recent call last):
File "my.py", line 9, in <module>
ob.stackoverflow()
TypeError: stackoverflow() takes exactly 2 arguments (1 given)
我该怎么做呢?
在3.4之前,agf的答案是正确的,而现在有了PEP-3124,我们得到了语法糖。
有关@overload装饰器的详细信息,请参阅typing文档,但请注意,这真的只是语法糖,恕我冒犯,这是人们一直在争论的问题。
就我个人而言,我同意拥有多个具有不同签名的函数比拥有一个具有20多个参数都设置为默认值(大多数时候没有)的单一函数更具可读性,然后不得不使用无休止的if, elif, else链来找出调用者实际希望我们的函数对所提供的参数集做什么。在Python禅之后,这是早就该有的:
美总比丑好。
也可以说
简单比复杂好。
直接来自上面链接的Python官方文档:
from typing import overload
@overload
def process(response: None) -> None:
...
@overload
def process(response: int) -> Tuple[int, str]:
...
@overload
def process(response: bytes) -> str:
...
def process(response):
<actual implementation>
编辑:如果有人想知道为什么这个例子不能像你从其他语言中期望的那样工作,我建议看看这个讨论。@overloaded函数不应该有任何实际的实现。这在Python文档中的示例中并不明显。
这是方法重载,而不是方法重写。在Python中,你可以在一个函数中完成所有工作:
class A:
def stackoverflow(self, i='some_default_value'):
print('only method')
ob=A()
ob.stackoverflow(2)
ob.stackoverflow()
请参阅Python教程的默认实参值部分。请参阅“Least surprise”和可变默认参数,以了解需要避免的常见错误。
有关Python 3.4中添加的单个分派泛型函数的信息,请参阅PEP 443:
>>> from functools import singledispatch
>>> @singledispatch
... def fun(arg, verbose=False):
... if verbose:
... print("Let me just say,", end=" ")
... print(arg)
>>> @fun.register(int)
... def _(arg, verbose=False):
... if verbose:
... print("Strength in numbers, eh?", end=" ")
... print(arg)
...
>>> @fun.register(list)
... def _(arg, verbose=False):
... if verbose:
... print("Enumerate this:")
... for i, elem in enumerate(arg):
... print(i, elem)
在MathMethod.py文件中:
from multipledispatch import dispatch
@dispatch(int, int)
def Add(a, b):
return a + b
@dispatch(int, int, int)
def Add(a, b, c):
return a + b + c
@dispatch(int, int, int, int)
def Add(a, b, c, d):
return a + b + c + d
在Main.py文件
import MathMethod as MM
print(MM.Add(200, 1000, 1000, 200))
我们可以使用multipledispatch重载该方法。
Python 3.5增加了类型模块。这包括一个重载装饰器。
这个装饰器的目的是帮助类型检查器。功能上它只是鸭子打字。
from typing import Optional, overload
@overload
def foo(index: int) -> str:
...
@overload
def foo(name: str) -> str:
...
@overload
def foo(name: str, index: int) -> str:
...
def foo(name: Optional[str] = None, index: Optional[int] = None) -> str:
return f"name: {name}, index: {index}"
foo(1)
foo("bar", 1)
foo("bar", None)
这将导致vs code中的以下类型信息:
虽然这可能有所帮助,但请注意,这添加了许多“奇怪的”新语法。它的目的——纯粹的类型提示——不是很明显。
使用类型的联合通常是更好的选择。