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

我该怎么做呢?


当前回答

在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中,重载不是一个应用概念。然而,如果你试图创建这样的情况,例如,你想要在传入类型为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'
         ...

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

在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重载该方法。

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

你也可以使用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.2.1写了我的答案。

def overload(*functions):
    return lambda *args, **kwargs: functions[len(args)](*args, **kwargs)

工作原理:

Overload接受任意数量的可调用对象,并将它们存储在元组函数中,然后返回lambda。 接受任意数量的参数, 然后返回存储在函数[number_of_unnamed_args_passed]中的调用函数的结果,并将参数传递给lambda。

用法:

class A:
    stackoverflow=overload(                    \
        None, \ 
        #there is always a self argument, so this should never get called
        lambda self: print('First method'),      \
        lambda self, i: print('Second method', i) \
    )