我试图在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)

我该怎么做呢?


当前回答

我想你想说的是"超载"Python中没有任何方法重载。但是,您可以使用默认参数,如下所示。

def stackoverflow(self, i=None):
    if i != None:
        print 'second method', i
    else:
        print 'first method'

当您向它传递一个参数时,它将遵循第一个条件的逻辑并执行第一个print语句。当你不给它传递参数时,它将进入else条件并执行第二个print语句。

其他回答

在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)

你也可以使用pythonlangutil:

from pythonlangutil.overload import Overload, signature

class A:
    @Overload
    @signature()
    def stackoverflow(self):    
        print('first method')
    
    @stackoverflow.overload
    @signature("int")
    def stackoverflow(self, i):
        print('second method', i)

Python 3。X包含标准类型库,允许使用@overload装饰器进行方法重载。不幸的是,这是为了使代码更具可读性,因为@overload装饰方法之后需要跟随一个处理不同参数的非装饰方法。 除了你的例子,你可以在这里找到更多:

from typing import overload
from typing import Any, Optional
class A(object):
    @overload
    def stackoverflow(self) -> None:    
        print('first method')
    @overload
    def stackoverflow(self, i: Any) -> None:
        print('second method', i)
    def stackoverflow(self, i: Optional[Any] = None) -> None:
        if not i:
            print('first method')
        else:
            print('second method', i)

ob=A()
ob.stackoverflow(2)

我用Python 2.7写了我的答案:

在Python中,方法重载是不可能的;如果你真的想用不同的特性访问同一个函数,我建议你使用方法重写。

class Base(): # Base class
    '''def add(self,a,b):
        s=a+b
        print s'''

    def add(self,a,b,c):
        self.a=a
        self.b=b
        self.c=c

        sum =a+b+c
        print sum

class Derived(Base): # Derived class
    def add(self,a,b): # overriding method
        sum=a+b
        print sum



add_fun_1=Base() #instance creation for Base class
add_fun_2=Derived()#instance creation for Derived class

add_fun_1.add(4,2,5) # function with 3 arguments
add_fun_2.add(4,2)   # function with 2 arguments