python中一个类中具有相同名称的方法?

时间:2011-02-22 14:48:37

标签: python overloading

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

我必须在这堂课中改变:

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

10 个答案:

答案 0 :(得分:55)

你可以拥有一个接受可变数量参数的函数。

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}

所以你可以按如下方式修改你的功能:

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

答案 1 :(得分:21)

你做不到。没有重载或多方法或类似的东西。一个名字指的是一件事。至于语言无论如何,你总是可以自己模仿它们......你可以用isinstance 检查类型(但请正确地做 - 例如在Python 2中,使用{{ 1}}检测字符串和unicode),但它很难看,一般不鼓励,很少有用。如果方法做了不同的事情,请给它们不同的名称。也考虑多态性。

答案 2 :(得分:4)

简答:你不能(see this previous discussion)。通常你会使用类似的东西(你可以添加更多类型检查和重新排序):

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

答案 3 :(得分:1)

您可以在Python中尝试多方法:

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

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

答案 4 :(得分:1)

使用 Python 3.5 或更高版本,您可以使用 @typing.overload 为重载的函数/方法提供类型注释。

From the docs

@overload
def process(response: None) -> None:
    ...
@overload
def process(response: int) -> tuple[int, str]:
    ...
@overload
def process(response: bytes) -> str:
    ...
def process(response):
    <actual implementation>

答案 5 :(得分:0)

Python与Java完全不同。

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

有一种方法可以测试传递的对象是否来自一个类,但主要是不好的做法。

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

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

对于第三个,好吧......使用不同的名字......

答案 6 :(得分:0)

您可能想要一个类似于以下的模式: 请注意,在方法名称的开头添加“_”是标记私有方法的约定。

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

答案 7 :(得分:0)

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

答案 8 :(得分:0)

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

说,你从一个需要使用两个参数的方法开始

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

然后你需要添加一个只有第二个参数的变体(比如,因为整数是多余的),解决方案非常简单:

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

这个解决方案的优点在于,无论调用代码之前是否使用了关键字参数或位置参数,它仍然可以继续工作。

答案 9 :(得分:0)

这不起作用。无论您有多少个参数,名称m都将被第二个m方法覆盖。

class C:
    def m(self):
        print('m first')
    def m(self, x):
        print(f'm second {x}')


ci=C();
#ci.m() # will not work TypeError: m() missing 1 required positional argument: 'x'
ci.m(1) # works

输出将很简单:

m second 1