我正在尝试在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)
我如何使这项工作?
答案 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)
工作原理:
overload
获取任意数量的callables并将它们存储在元组functions
中,然后返回lambda。functions[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) \
)
答案 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。
的礼貌答案 11 :(得分:3)
虽然@agf过去用PEP-3124正确地回答了问题,但我们得到了语法建议。请参见@overload
装饰器上的typing documentation for details,但请注意,这实际上只是语法建议者,恕我直言,这是从那时起人们一直在争论的问题。我个人认为,具有多个具有不同签名的功能会使其更具可读性,然后将单个功能的20个以上的参数都设置为默认值(大多数情况下为None
),然后不得不使用无休止的{{ 1}},if
,elif
链来找出调用者实际上希望我们的函数使用提供的参数集做什么。在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 name
和different 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