我试图在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中,您可以使用默认参数来完成此操作。

class A:

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

其他回答

在Python中,重载不是一个应用概念。然而,如果你试图创建这样的情况,例如,你想要在传入类型为foo的参数时执行一个初始化式,而在传入类型为bar的参数时执行另一个初始化式,那么,由于Python中的所有内容都是作为对象处理的,你可以检查传入对象的类类型的名称,并基于此编写条件处理。

class A:
   def __init__(self, arg)
      # Get the Argument's class type as a String
      argClass = arg.__class__.__name__

      if argClass == 'foo':
         print 'Arg is of type "foo"'
         ...
      elif argClass == 'bar':
         print 'Arg is of type "bar"'
         ...
      else
         print 'Arg is of a different type'
         ...

这个概念可以根据需要通过不同的方法应用到多个不同的场景中。

在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文档中的示例中并不明显。

我刚刚遇到了重载.py (Python 3的函数重载),有兴趣的同学可以去看看。

从链接库的README文件:

overloading is a module that provides function dispatching based on the types and number of runtime arguments. When an overloaded function is invoked, the dispatcher compares the supplied arguments to available function signatures and calls the implementation that provides the most accurate match. Features Function validation upon registration and detailed resolution rules guarantee a unique, well-defined outcome at runtime. Implements function resolution caching for great performance. Supports optional parameters (default values) in function signatures. Evaluates both positional and keyword arguments when resolving the best match. Supports fallback functions and execution of shared code. Supports argument polymorphism. Supports classes and inheritance, including classmethods and staticmethods.

你也可以使用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中,所有东西都是对象。类是事物,所以它们是对象。方法也是如此。

有一个对象叫做A,它是一个类。它有一个名为stackoverflow的属性。它只能有一个这样的属性。

当你写def stackoverflow(…):…,所发生的是你创建一个对象,它是方法,并将它赋值给a的stackoverflow属性。如果你写了两个定义,第二个会替换第一个,这与赋值的行为相同。

此外,您也不希望编写的代码执行重载有时会用到的那种过分的操作。语言不是这样的。

与其尝试为可能给定的每种类型的东西定义一个单独的函数(这没什么意义,因为你没有为函数参数指定类型),不如停止担心这些东西是什么,开始思考它们能做什么。

您不仅不能单独编写一个来处理元组和列表,而且也不想或不需要这样做。

你所要做的就是利用它们都是可迭代的这一事实,例如,你可以写for element in container:)。(他们之间没有直接的遗传关系,这一点无关紧要。)