method overloading in python
我需要调用非参数化方法
1 2 3 4 5 6 7 8 9 10 11 | >>> class A: ... def first(self): ... print 'first method' ... def first(self,f): ... print 'first met',f ... >>> a=A() >>> a.first() Traceback (most recent call last): File"<stdin>", line 1, in <module> TypeError: first() takes exactly 2 arguments (1 given) |
在Java中像Python那样执行方法重载是可能的吗?
您的第二个
但是,您可以使用可选和/或基于关键字的参数创建方法,并相应地处理这些参数。下面是一个例子:
1 2 3 4 5 6 | class A: def first(self, f=None): if f is not None: print 'first met', f else: print 'first method' |
用途:
1 2 3 | a = A() a.first() a.first('something') |
号
python不执行函数重载。这是因为它是一种松散类型的语言。相反,您可以指定未知数量的参数,并在函数逻辑中处理它们的解释。
有几种方法可以做到这一点。您可以指定特定的可选参数:
1 2 3 4 5 | def func1(arg1, arg2=None): if arg2 != None: print"%s %s" % (arg1, arg2) else: print"%s" % (arg1) |
我们称之为:
1 2 | >>> func1(1, 2) 1 2 |
。
或者可以指定未知数量的未命名参数(即数组中传递的参数):
1 2 3 4 5 6 | def func2(arg1, *args): if args: for item in args: print item else: print arg1 |
我们称之为:
1 2 3 4 5 | >>> func2(1, 2, 3, 4, 5) 2 3 4 5 |
。
或者,您可以指定未知数目的命名参数(即字典中传递的参数):
1 2 3 4 5 6 | def func3(arg1, **args): if args: for k, v in args.items(): print"%s %s" % (k, v) else: print arg1 |
号
我们称之为:
1 2 3 | >>> func3(1, arg2=2, arg3=3) arg2 2 arg3 3 |
号
您可以使用这些构造来产生您在重载中寻找的行为。
通常,在具有给定名称的类中只能定义一个方法。在您的示例中,2 argument first()方法首先覆盖1 argument()。如果您想要两个同名的方法,在python 3中,您必须使用functools.singledispatch,并将实例方法名映射到静态方法调度器,哎呀!
也就是说,我真的很喜欢OO编程中的隐式动态分派,我发现它比在某种"master"first()函数中编写手动分派逻辑更干净,这种函数重复且易于扩展。
挑战问题:添加另一个方法,如a.first(arg)。
如果您尝试这样做,您可能会学到很多关于Python类型系统的知识!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | #!/opt/local/bin/python3.4 from functools import singledispatch; class A(object): # default method handles dispatch for undefined types # note reversed positional args to match single dispatch functools @singledispatch def _first(self,arg): raise TypeError("no match for A._first(%s)" % type(arg)); # adapter maps instance call to (reversed) static method call def first(self, arg = None): return A._first(arg, self); # def first() @_first.register(type(None)) def _(self,none): print("A.first() called"); # def first(float f) @_first.register(float) def _(self,f): print("A.first(float %s) called" % f); a = A(); a.first(); # A.first() called a.first(None); # A.first() called a.first(3.14); # A.first(float 3.14) called class B(object): pass; b = B(); try: a.first(b); # no match for A._first(<class '__main__.B'>) except TypeError as ex: print(ex); |
号
如果有帮助,请检查此代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | from math import pi class Geometry: def area(self,length = None,breadth = None,side = None,radius = None): self.length = length self.breadth = breadth self.side = side self.radius = radius if length != None and breadth != None: return length * breadth elif side != None: return side * side else: return pi * radius * radius obj1 = Geometry() print('Area of rectangle is {0}.'.format(obj1.area(length=5,breadth=4))) print('Area of square is {0}.'.format(obj1.area(side=5))) print('Area of circle is {0:.6}.'.format(obj1.area(radius=10))) |
号
虽然可以创建一个似乎使用重载方法的系统,但它有点复杂,通常不需要。
通常的习惯用法是将可能不需要的参数默认为
1 2 3 4 5 6 | class A: def first(self, f=None): if f is None: print 'first method' else: print 'first met',f |
。
在您的情况下,如果您希望根据这是否是对该方法的第一个调用来实现不同的行为,我将这样做:
1 2 3 4 5 6 | class A: def first(self): print 'first method' self.first = self._first def _first(self, f): # '_' is convention for private name print 'first met',f |
样本输出:
1 2 3 | a = A() a.first() a.first(3) |
。
印刷品:
1 2 | first method first met 3 |
。
Python不是C++或Java;不能以相同的方式重载方法。
实际上,执行您想要的操作的唯一方法是测试是否存在第二个参数:
1 2 3 4 5 6 | class A: def first(self, f=None): if f is None: print 'first method' else: print 'first met',f |
你可以更加复杂地检查