如何在一个类中声明几个同名但参数数量或类型不同的方法?
下节课我必须改变什么?
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
您可以拥有一个接受可变数量参数的函数。
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
你不能。没有重载或多重方法或类似的东西。一个名字指的是一件事。无论如何,就语言而言,您始终可以自己模拟它们...您可以使用 isinstance
检查类型(但请正确执行 - 例如,在 Python 2 中,使用
basestring
来检测字符串和 unicode ),但它很丑陋,通常不鼓励并且很少有用。如果这些方法执行不同的操作,请为它们指定不同的名称。还要考虑多态性。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
没有真正的类型,只有带有方法的对象。
有一种方法可以测试传递的对象是否来自类,但这主要是不好的做法。
但是,您想要为前两个方法生成的代码应该类似于
class MyClass(object):
def my_method(self, str1, str2=None):
print str1
if str2: print str2
对于第三个,嗯...使用不同的名称...
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
假设您从一个需要使用两个参数的方法开始
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")
这个解决方案的好处是,无论调用代码之前使用了关键字参数还是位置参数,它仍然可以继续工作。
@overload
解决了这个问题:VS Code -> f12 on
open()
-> 它显示了一堆 open()
函数的重复项:@overload
def open(...):
@overload
def open(...):
...
所以,这就是结果...
class MyClass:
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
@overload
def my_method(self,parameter_A_that_Must_Be_String):
print parameter_A_that_Must_Be_String
@overload
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
@overload
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
抱歉让你紧张了......