我试图在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在PEP-3124中添加了@overload装饰器,为通过类型检查进行重载提供语法糖——而不仅仅是使用重写。

关于通过PEP-3124中的@overload重载的代码示例

from overloading import overload
from collections import Iterable

def flatten(ob):
    """Flatten an object to its component iterables"""
    yield ob

@overload
def flatten(ob: Iterable):
    for o in ob:
        for ob in flatten(o):
            yield ob

@overload
def flatten(ob: basestring):
    yield ob

由@overload-decorator转换为:

def flatten(ob):
    if isinstance(ob, basestring) or not isinstance(ob, Iterable):
        yield ob
    else:
        for o in ob:
            for ob in flatten(o):
                yield ob

其他回答

我刚刚遇到了重载.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.

你不能,永远不需要,也不想这么做。

在Python中,所有东西都是对象。类是事物,所以它们是对象。方法也是如此。

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

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

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

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

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

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

有一些库可以简化这个过程:

Functools -如果你只需要第一个参数,使用@singledispatch

李子调度-功能丰富的方法/函数重载。

多调度-替代梅花少功能,但轻量级。

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)

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