我尝试在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
ob.stackoverflow()
TypeError: stackoverflow() takes exactly 2 arguments (1 given)
我该怎么做?
在Python中,将方法视为一组特殊的"属性",一个对象的给定名称只能有一个"属性"(因此一个方法)。最后一个方法覆盖任何以前的方法。在Java中,方法不是一流的公民(它们不是"对象的属性"),而是由"基于最接近类型的静态解析的发送消息"(即重载进来的地方)调用。
另请参见stackoverflow.com/questions/733264/…
和stackoverflow.com/questions/6434482/python函数重载‌&8203;ing
为什么这个问题的答案还没有被接受?只需点击你最喜欢的答案左边的"离群"复选标记…
可能是Python中重载函数的副本?
它是方法重载,而不是方法重写。在Python中,您可以在一个函数中完成所有操作:
class A:
def stackoverflow(self, i='some_default_value'):
print 'only method'
ob=A()
ob.stackoverflow(2)
ob.stackoverflow()
在Python中,不能有两个同名的方法——而且不需要这样做。
请参见Python教程的"默认参数值"部分。请参阅"最小惊异"和可变默认参数,了解要避免的常见错误。
编辑:有关python 3.4中新的单分派通用函数的信息,请参阅pep 443。
你不需要- IMHO有时会非常方便的方法重载,例如在C++中。好吧,从某种意义上说,它不是"必需的",因为它不能用其他构造来完成——但它会使一些事情变得更容易和简单。
@安德烈亚斯弗洛拉,我不同意。学着喜欢duck打字和写每一个方法,这样它只做一件事,而不需要方法重载。
是的,我需要它,因为我用C++编写,因此用C++来思考。现在明白
+在我被抓之前让我读到"避免的常见错误"
我有点不同意;)…重载通常会使代码更干净,因为您不需要用太多if-else语句来打包方法来处理不同的情况。在某种意义上,函数语言的整个范围都使用类似的概念,即参数模式匹配。这意味着你会有更小更干净的方法。而不是巨大的不可读的。
@user1019129这是在python 3.4中添加并在我的答案中链接的单个分派通用函数的目的。
因此,如果我们需要多个重载,这些重载根据不同的参数集执行不同的操作,那么我们必须显式地对传递给"单调度泛型函数"的不同参数执行if:、elif:?
@Mahesha999我不知道你在问什么。您不需要任何if来使用pep 443通用函数对单个参数进行分派。请阅读链接文档。
一个常见的误解是:默认参数值不能替代重载。比较Velocity(),表示速度为零,和Velocity(x,y,z)。在这种情况下,让它像Velocity(1,3)一样可以调用是没有意义的。同样,Position(x,y,z)与Position(position)的对比。
此外,您还说"不需要",这对于每个现实世界中的每个特性和图灵完整编程语言都是普遍正确的。然后以厚颜无耻的语气介绍Pep443。隐马尔可夫模型。
@Sebastianmach默认参数可以替换许多重载用例,方法中的其他逻辑可以替换其他用例。在您的示例中,您可以(并且人们经常这样做)将默认值设置为"无",并检查值以查看传递的内容。省略一个参数并不是使用默认参数所能做的唯一事情,而且如果人们以一种不合理的方式调用它,那么您总是可以引发一个参数错误。
@Sebastianmach您不需要在Python中进行方法重载,这并不是因为可以用其他方法进行操作,而是因为它通常是惯用的。""需要"比你在对这个答案和下面的另一个答案的评论中给出的狭义定义更为普遍。就PEP 443而言,在最初编写此答案时,它并不存在。我后来在一篇编辑文章中补充了这一点;我不知道你所说的"厚颜无耻的语气"是什么意思——我只是链接到它并描述它是什么。
@我不是真的在质疑(非)的"需要"。C++也不需要它们,比如C++不需要"智能指针",因为可以手动管理内存。重载只是框中的另一个工具;它可以将参数组合的显式和较慢的手动检查委托给解释器以实现调用解决级别。正如您所暗示的,它可以作为增强代码健壮性的工具(因为当您有重载时,解释器会为您进行检查)。
@阿格夫:我说的"厚颜无耻",是指像"它不存在是因为它不需要"这样的回答,看起来像是在向读者下线,这通常是不合理的。
当有人用"你不需要它"来描述一个缺失的特征时,认知失调就会在100英里之外出现。为了上帝的缘故,重载比默认值强得多。在Python中不存在继续解决大量其他问题的强类型,因为它是作为脚本语言而诞生的,并且最近它试图对其进行更改。欣赏Python作为一种好的脚本语言,但不要忘记它是什么。真正的重载需要区分类型的原型设计,像python这样的脚本语言不会这样做,因此会失去很多优雅和可读性。
@我认为你的整个评论是错误的,并且显示出你对像python这样的动态类型语言在规模上的使用缺乏经验。但是,如果您查看我答案底部的链接,您会发现python具有您在3.4+版本中描述的确切特性——基于类型的分派。
在python中,您不会这样做。当人们用Java语言这样做时,他们通常想要一个默认值(如果他们不这样,他们通常需要一个不同名称的方法)。所以,在python中,可以有默认值。
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
大多数情况下,当您需要可变的默认值时,None非常有用。单独的行为应该在单独的函数中。
@agf:None也可以作为真正的默认值使用。
是的,但我指的是把它作为一个哨兵值,这就是你在回答中使用它的方式,我认为我的评论很清楚。
您也可以使用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 decorator。
我认为这是对这个问题唯一有效的回答。如果可以的话,我会加倍投票。
很好,但它不适用于原始函数,只适用于类中的方法。
@请确认还可以添加功能。这并非不可能。
@Ehsankeshavarzian我确实把它添加到了我自己的版本中,并且它似乎可以工作,但是我不知道我做的是否正确。我还添加了允许签名成为字典的功能,这样您就可以指定参数的名称。这样,您就可以拥有两个具有相同类型签名但名称不同的函数,并且只要为参数命名,就可以区分这两个函数。
@Legitstack有多种方法。也有github.com/bintoro/overloading.py,但是有了python 3对重载的支持,我认为不再需要第三方库了。docs.python.org/3/library/typing.html typing.overload
你不能,不需要,也不想。
在Python中,一切都是一个对象。类是事物,所以它们是对象。方法也是如此。
有一个名为A的对象,它是一个类。它有一个名为stackoverflow的属性。它只能有一个这样的属性。
当您编写def stackoverflow(...): ...时,会发生的情况是创建一个对象,该对象就是方法,并将其分配给A的stackoverflow属性。如果编写两个定义,第二个定义将替换第一个定义,与赋值的行为方式相同。
此外,您不希望编写代码来执行有时使用重载的更疯狂的事情。这不是语言的工作方式。
不要试图为每种类型的对象定义一个单独的函数(这是毫无意义的,因为您无论如何都不为函数参数指定类型),不要担心这些对象是什么,开始考虑它们可以做什么。
您不仅不能编写单独的一个来处理元组和列表,而且也不想或不需要。
你所做的就是利用它们都是不可更改的这一事实(例如,你可以写for element in container:)。(事实上,它们与继承没有直接联系是不相关的。)
但是,我会更加小心"不需要"。这是可以标记在任何现实世界和图灵完整编程语言的每个特性上的东西,因此不是一个有效的论点。谁需要发电机?谁需要上课?编程语言只是一些更具体的东西的语法甜头。
完全不同意。也许你"从来没有必要"或者"从来没有想过",但是有足够多的应用程序是你非常想要的。例如,编写一个既能优雅地处理python数组又能处理numpy数组的程序,而不必在程序中乱丢instanceof的…
根据玛西的回答,我会说"你不能"现在是不正确和过时的。基于@overload装饰师的存在,我认为"不真的想"是可以论证的,充其量是可以的。从PEP-3124,"…目前,检查接收到的参数类型是Python代码的一种常见反模式……这样做的"明显方法"是通过类型检查,但这是脆弱的,并且接近扩展……"因此,似乎有足够多的人想要这样做,它成为了Python的一部分。
我用python 3.2.1编写了我的答案。
def overload(*functions):
return lambda *args, **kwargs: functions[len(args)](*args, **kwargs)
它是如何工作的:
overload接受任意数量的可调用文件并将其存储在tuple functions中,然后返回lambda。
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) \
)
这对我来说是最优雅的解决方案。
优雅一+ 1。
我认为你要找的词是"超载"。在Python中没有方法重载。但是,您可以使用默认参数,如下所示。
def stackoverflow(self, i=None):
if i != None:
print 'second method', i
else:
print 'first method'
当您传递一个参数时,它将遵循第一个条件的逻辑并执行第一个print语句。当您没有参数传递它时,它将进入else条件并执行第二个print语句。
我用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
干得好@matt谢谢
在Python中,重载不是一个应用的概念。但是,如果您试图创建这样一种情况:例如,如果传递了foo类型的参数,则需要执行一个初始值设定项;如果传递了bar类型的参数,则需要执行另一个初始值设定项;那么,由于python中的所有内容都是作为对象处理的,因此可以检查传递对象的类类型的名称,并编写条件h基于此进行处理。
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'
...
这个概念可以根据需要通过不同的方法应用到多个不同的场景中。
在python中,您可以使用默认参数来实现这一点。
class A:
def stackoverflow(self, i=None):
if i == None:
print 'first method'
else:
print 'second method',i
刚刚看到这个https://github.com/bintoro/overloading.py给任何可能感兴趣的人。
从链接存储库的自述文件中:
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.
虽然@agf过去对pep-3124的回答是正确的,但我们得到了语法建议。有关@overload装饰器的详细信息,请参阅键入文档,但请注意,这实际上只是语法sugger和imho,这是所有人从那以后一直在争论的问题。我个人认为,拥有多个具有不同签名的函数会使它更易于阅读,然后拥有一个具有20多个参数的函数,这些参数都设置为默认值(大多数情况下都是None,然后不得不使用无休止的if、elif、else链来查找调用者实际想要的内容。函数处理提供的参数集。这,这是在python zen之后很久以前的事了
Beautiful is better than ugly.
也可以说
Simple is better than complex.
直接从上面链接的官方python文档:
@overload
def process(response: None) -> None:
...
@overload
def process(response: int) -> Tuple[int, str]:
...
@overload
def process(response: bytes) -> str:
...
def process(response):
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)
我们需要提供可选参数或*参数,以便在调用时提供不同数量的参数。
由https://www.geeksforgeks.org/python-method-overloading提供/
python 3.x包含标准类型库,允许使用@overload decorator进行方法重载。不幸的是,这是为了提高代码的可读性,因为@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)
你答案末尾的"the"让我觉得你还没写完。请编辑您的答案以完成它。
在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来重载方法
这需要使用multipedispatch包(pypi.org/project/multipedispatch),该包不是Python核心的一部分。