python中的方法重载

2024-09-26 17:54:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我需要调用未命名的方法first,还需要参数化的方法first,但它给出了一个错误。

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

在Python中是否可以像在Java中那样进行方法重载?


Tags: 方法selfmost参数def错误callmethod
3条回答

Python不做函数重载。这是它是一种松散类型语言的结果。相反,您可以指定未知数量的参数,并在函数逻辑中处理它们的解释。

有几种方法可以做到这一点。可以指定特定的可选参数:

def func1(arg1, arg2=None):
    if arg2 != None:
        print "%s %s" % (arg1, arg2)
    else:
        print "%s" % (arg1)

我们称之为:

>>> func1(1, 2)
1 2

或者可以指定未知数量的未命名参数(即在数组中传递的参数):

def func2(arg1, *args):
    if args:
        for item in args:
            print item
    else:
        print arg1

我们称之为:

>>> func2(1, 2, 3, 4, 5)
2
3
4
5

或者可以指定未知数量的命名参数(即在字典中传递的参数):

def func3(arg1, **args):
    if args:
        for k, v in args.items():
            print "%s %s" % (k, v)
    else:
        print arg1

我们称之为:

>>> func3(1, arg2=2, arg3=3)
arg2 2
arg3 3

您可以使用这些构造来产生您在重载中寻找的行为。

通常在一个具有给定名称的类中只能定义一个方法。在您的示例中,2 argument first()方法覆盖了1 argument first()。如果您想要两个同名的方法,那么在python 3中,您必须使用functools.singledispatch,并将实例方法名称映射到静态方法调度器,哎哟!

也就是说,我真的很喜欢OO编程中的动态调度,我发现它比在某种“master”first()函数中编写手动调度逻辑更干净,这种函数重复性强,扩展性差。

挑战问题:添加另一个方法,如A.first(A arg)。

如果您尝试这样做,您可能会学到很多关于python类型系统的知识!

#!/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);

您的第二个first方法正在重写原始的first方法。在Python中,不可能像在Java中那样创建重载方法。

但是,您可以创建具有基于可选和/或关键字的参数的方法,并相应地处理这些参数。下面是一个例子:

class A:
    def first(self, f=None):
        if f is not None:
            print 'first met', f
        else:
            print 'first method'

用法:

a = A()
a.first()
a.first('something')

相关问题 更多 >

    热门问题