如何在Python中使用方法重载?

时间:2012-04-18 04:47:50

标签: python class overloading

我正在尝试在Python中实现方法重载:

class A:
    def stackoverflow(self):    
        print 'first method'
    def stackoverflow(self, i):
        print 'second method', i

ob=A()
ob.stackoverflow(2)

但输出为second method 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)

我如何使这项工作?

16 个答案:

答案 0 :(得分:133)

方法重载而不是方法重写。在Python中,您可以在一个函数中完成所有操作:

class A:

    def stackoverflow(self, i='some_default_value'):    
        print 'only method'

ob=A()
ob.stackoverflow(2)
ob.stackoverflow()

在Python中不能有两个具有相同名称的方法 - 而且您不需要。

请参阅Python教程的Default Argument Values部分。有关要避免的常见错误,请参阅"Least Astonishment" and the Mutable Default Argument

编辑:有关Python 3.4中新的单一调度通用函数的信息,请参阅PEP 443

答案 1 :(得分:45)

在Python中,你不会那样做。当人们使用Java这样的语言时,他们通常需要一个默认值(如果他们不这样做,他们通常需要一个名称不同的方法)。所以,在Python中,you can have default values

class A(object):  # Remember the ``object`` bit when working in Python 2.x

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

如您所见,您可以使用它来触发单独的行为,而不仅仅是具有默认值。

>>> ob = A()
>>> ob.stackoverflow()
first form
>>> ob.stackoverflow(2)
second form

答案 2 :(得分:42)

您还可以使用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中官方支持重载,您可以使用@overload装饰器。

答案 3 :(得分:25)

你不能,永远不需要也不想真。

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

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

当您编写def stackoverflow(...): ...时,会发生的情况是您创建一个方法对象,并将其分配给stackoverflow的{​​{1}}属性。如果你写两个定义,第二个定义替换第一个,就像赋值总是表现一样。

此外,您不希望编写代码,这些代码可以解决有时用于重载的各种事物。这不是语言的运作方式。

而不是尝试为每种类型的事物定义一个单独的函数(由于你没有指定函数参数的类型,这没什么意义),不再担心是什么并开始考虑他们可以做什么

您不仅不能单独编写一个元组来处理元组与列表,还不想要或不需要

您所做的只是利用它们都是可迭代的事实(即您可以编写A)。 (它们与继承没有直接关联的事实是无关紧要的。)

答案 4 :(得分:17)

我在Python 3.2.1中写了我的答案。

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

工作原理:

  1. overload获取任意数量的callables并将它们存储在元组functions中,然后返回lambda。
  2. lambda接受任何数量的参数, 然后返回存储在functions[number_of_unnamed_args_passed]中的调用函数的结果,该函数使用传递给lambda的参数调用。
  3. 用法:

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

答案 5 :(得分:13)

我认为你正在寻找的是&#34;重载&#34;。 python中没有方法重载。但是,您可以使用默认参数,如下所示。

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

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

答案 6 :(得分:12)

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

答案 7 :(得分:9)

在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'
         ...

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

答案 8 :(得分:7)

在Python中,您可以使用默认参数执行此操作。

class A:

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

答案 9 :(得分:5)

对于任何可能感兴趣的人来说,只是遇到了这个https://github.com/bintoro/overloading.py

来自链接存储库的自述文件:

  

重载是一个基于提供函数调度的模块   运行时参数的类型和数量。

     

当调用重载函数时,调度程序会比较   提供可用函数签名的参数并调用   提供最准确匹配的实现。

     

功能

     

注册时的功能验证和详细的解决规则   在运行时保证唯一,明确定义的结果。器物   功能解析缓存以获得出色的性能。支持可选   函数签名中的参数(默认值)。评估两者   解决最佳匹配时的位置和关键字参数。   支持回退功能和共享代码的执行。支持   参数多态性。支持类和继承,包括   classmethods和staticmethods。

答案 10 :(得分:3)

Python不支持像Java或C ++这样的方法重载。我们可能会重载方法,但只能使用最新定义的方法。

# First sum method.
# Takes two argument and print their sum
def sum(a, b):
    s = a + b
    print(s)

# Second sum method
# Takes three argument and print their sum
def sum(a, b, c):
    s = a + b + c
    print(s)

# Uncommenting the below line shows an error    
# sum(4, 5)

# This line will call the second sum method
sum(4, 5, 5)

我们需要提供可选参数或* args,以便在调用时提供不同数量的args。

来自https://www.geeksforgeeks.org/python-method-overloading/

的礼貌

答案 11 :(得分:3)

虽然@agf过去用PEP-3124正确地回答了问题,但我们得到了语法建议。请参见@overload装饰器上的typing documentation for details,但请注意,这实际上只是语法建议者,恕我直言,这是从那时起人们一直在争论的问题。我个人认为,具有多个具有不同签名的功能会使其更具可读性,然后将单个功能的20个以上的参数都设置为默认值(大多数情况下为None),然后不得不使用无休止的{{ 1}},ifelif链来找出调用者实际上希望我们的函数使用提供的参数集做什么。在Python Zen

之后,这早就该了
  

美丽胜于丑陋。

也可以说

  

简单胜于复杂。

直接从上面链接的官方Python文档中获取:

else

答案 12 :(得分:2)

Python 3.x包含标准的类型库,该库允许使用@overload装饰器来重载方法。不幸的是,这是为了使代码更具可读性,因为@overload装饰的方法将需要后面跟随一个处理不同参数的非装饰方法。 在这里here可以找到更多信息,但以您的示例为例:

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)

答案 13 :(得分:2)

实际上在 Python 中,方法重载是不可能的。如果python虚拟机看到任何带有same namedifferent number of arguments的方法,它只会认为last method

这里

class A:
    def stackoverflow(self):    
        print 'first method'
    def stackoverflow(self, i):
        print 'second method', i

ob=A()
ob.stackoverflow(2) // second method 2

在这种情况下,PVM 仅考虑 second method,因此如果您传递任何参数(或不传递参数),它会调用需要参数 i 的第二个方法。如果我们调用方法 stackoverflow without any argument 它会给出一个 error

但是如果我们需要python中方法重载的功能,我们可以使用default arguments方法。

使用默认数量的参数

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

ob=A()
ob.stackoverflow()  // first method
ob.stackoverflow(2) // second method 2

答案 14 :(得分:0)

在MathMethod.py文件中

java.time

在Main.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

我们可以使用multipledispatch

重载方法

答案 15 :(得分:0)

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