关于重载:在Python的一个类中使用相同名称的方法?

Methods with the same name in one class in python?

如何在一个类中声明几个具有相同名称但具有不同数量参数或不同类型的方法?

在这门课上我必须改变的是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class MyClass:
   """"""

    #----------------------------------------------------------------------
    def __init__(self):
       """Constructor"""
    def my_method(self,parameter_A_that_Must_Be_String):
        print parameter_A_that_Must_Be_String

    def my_method(self,parameter_A_that_Must_Be_String,parameter_B_that_Must_Be_String):
        print parameter_A_that_Must_Be_String
        print parameter_B_that_Must_Be_String

    def my_method(self,parameter_A_that_Must_Be_String,parameter_A_that_Must_Be_Int):
        print parameter_A_that_Must_Be_String * parameter_A_that_Must_Be_Int


您可以有一个接受可变参数数目的函数。

1
2
3
4
5
6
7
8
9
def my_method(*args, **kwds):
    # do something

# when you call the method
my_method(a1, a2, k1=a3, k2=a4)

# you get:
args = (a1, a2)
kwds = {'k1':a3, 'k2':a4}

因此,您可以按如下方式修改您的函数:

1
2
3
4
5
6
7
def my_method(*args):
    if len(args) == 1 and isinstance(args[0], str):
        # case 1
    elif len(args) == 2 and isinstance(args[1], int):
        # case 2
    elif len(args) == 2 and isinstance(args[1], str):
        # case 3


不能。没有重载、多方法或类似的东西。一个名字指的是一件事。就语言而言,你总是可以自己模仿它们…您可以使用isinstance检查类型(但请正确地进行检查—例如,在python 2中,使用basestring检测字符串和unicode),但它很难看,通常不鼓励使用,而且很少有用。如果方法做了不同的事情,给它们取不同的名称。考虑多态性。


简短回答:你不能(见前面的讨论)。通常您会使用类似的方法(您可以添加更多类型检查和重新排序):

1
2
3
4
5
6
7
def my_method(self,parameter_A, parameter_B=None):
  if isinstance(parameter_B, int):
    print parameter_A * parameter_B
  else:
    print parameter_A
    if parameter_B is not None:
      print parameter_B

您可以在python中尝试多种方法:

http://www.artima.com/weblogs/viewpost.jsp?线程=101605

但我不认为多方法是一种可行的方法。相反,传递给方法的对象应该具有公共接口。您正在尝试实现类似于C++中的方法重载,但在Python中很少需要这种方法。一种方法是使用isinstance级联ifs,但这很难看。


我认为所有答案中都缺少一个非常简单的例子,那就是:当方法变化之间的唯一区别是参数的数量时,该怎么做。答案仍然是使用参数数目可变的方法。

例如,您从一个需要使用两个参数的方法开始

1
2
def method(int_a, str_b):
    print("Got arguments: '{0}' and '{1}'".format(int_a, str_b)

然后您需要添加一个变量,只使用第二个参数(例如,因为整数是多余的),解决方案非常简单:

1
2
3
4
5
6
7
8
9
10
11
12
13
def _method_2_param(int_a, str_b):
    print("Got arguments: '{0}' and '{1}'".format(int_a, str_b))

def _method_1_param(str_b):
    print("Got argument: '{0}'".format(str_b))

def method(*args, **kwargs):
    if len(args) + len(kwargs) == 2:
        return _method_2_param(args, kwargs)
    elif len(args) + len(kwargs) == 1:
        return _method_1_param(args, kwargs)
    else:
        raise TypeError("Method requires one or two arguments")

这个解决方案的好处在于,无论调用代码以前使用过关键字参数还是位置参数,它都将继续工作。


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
35
class MyClass:
    def __init__(this, foo_str, bar_int):
        this.__foo = foo_str
        this.__bar = bar_int

    def foo(this, new=None):
        if new != None:
            try:
                this.__foo = str(new)
            except ValueError:
                print("Illegal value. foo unchanged.")

        return this.__foo

    def bar(this, new=None):
        if new != None:
            try:
                this.__bar = int(new)
            except ValueError:
                print("Illegal value. bar unchanged.")

        return this.__bar

obj = MyClass("test", 42)
print(obj.foo(), obj.bar())

print(obj.foo("tset"), obj.bar(24))

print(obj.foo(42), obj.bar("test"))

Output:
    test 42
    tset 24
    Illegal value. bar unchanged.
    42 24


您可能需要类似以下的模式:请注意,在方法名称的开头添加"u"是标记私有方法的约定。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class MyClass:
   """"""

    #----------------------------------------------------------------------
    def __init__(self):
       """Constructor"""
    def my_method(self,parameter_A_that_Must_Be_String, param2=None):
        if type(param2) == str:
            return self._my_method_extra_string_version(parameter_A_that_Must_Be_String, param2)
        elif type(param2) == int:
            return self._my_method_extra_int_version(parameter_A_that_Must_Be_String, param2)
        else:
            pass # use the default behavior in this function
        print parameter_A_that_Must_Be_String

    def _my_method_extra_string_version(self,parameter_A_that_Must_Be_String, parameter_B_that_Must_Be_String):
        print parameter_A_that_Must_Be_String
        print parameter_B_that_Must_Be_String

    def _my_method_extra_int_version(self,parameter_A_that_Must_Be_String, parameter_A_that_Must_Be_Int):
        print parameter_A_that_Must_Be_String * parameter_A_that_Must_Be_Int


Python与Java无关。

没有真正的类型,只有带有方法的对象。

有一种方法可以测试通过的对象是否来自某个类,但这主要是坏的实践。

但是,要为前两个方法生成的代码应该类似于

1
2
3
4
class MyClass(object):
    def my_method(self, str1, str2=None):
        print str1
        if str2: print str2

第三个,嗯…使用其他名称…