如何在Python中编写参数不同的同名方法
我正在学习Python(3.x),之前是用Java的。
我有一个Python程序,在里面我创建了一个personObject,并把它添加到一个列表里。
p = Person("John")
list.addPerson(p)
但是为了灵活性,我还想直接在addPerson方法里声明它,像这样:
list.addPerson("John")
addPerson方法能够区分我传入的是一个Person对象还是一个字符串。
在Java中,我会创建两个不同的方法,像这样:
void addPerson(Person p) {
# Add a person to the list
}
void addPerson(String personName) {
# Create a 'Person' object
# Add a person to the list
}
但我不知道在Python中怎么做到这一点。我知道有一个type()函数,可以用来检查参数是字符串还是对象。不过,我觉得这样有点麻烦。有没有其他的方法呢?
我想另一个解决办法可能是这样的(Python):
def addPerson(self, person):
# Check if 'person' is a string
# Create a person object
# Check that a person is a Person instance
# Do nothing
# Add person to list
但相比于Java的重载方案,这样看起来有点乱。
2 个回答
1
我用过的一种常见方法来实现这个特定的模式是这样的:
def first(self, person):
try:
person = Person(person)
except ConstructionError as e:
pass
# Do your thing
我不知道这个方法对你是否有效。你想要捕捉到任何可能由Person
生成的错误,特别是当你用一个已经存在的Person
来调用它的时候。如果能用person_factory
来处理,那就更好了,因为它可以直接返回已经存在的对象,而不是抛出一个异常。
在Python中,多重方法的实现方式有些不同;Python允许你几乎可以实现任何你想要的语义接口,虽然这可能会在后台增加一些额外的工作,但你通常可以调整这些“额外工作”的位置,以便更好地隐藏它。
另外,这样做还有一些好处……你有时会在C++、C#和Java中看到类似的东西:
int sum(int a, int b) {
return (a+b)
}
float sum (float a, float b) {
return (a+b)
}
etc.
在Python中可以用下面的方式替代:
def sum(a,b):
return a+b
(不过据我所知,C++和C#现在也有auto
,可以处理类似的情况)。
8
根据Kevin提供的参考链接,你可以这样做:
from multimethod import multimethod
class Person(object):
def __init__(self, myname):
self.name = myname
def __str__(self):
return self.name
def __repr__(self):
return self.__str__()
@multimethod(list, object)
def addPerson(l, p):
l = l +[p]
return l
@multimethod(list, str)
def addPerson(l, name):
p = Person(name)
l = l +[p]
return l
alist = []
alist = addPerson(alist, Person("foo"))
alist = addPerson(alist, "bar")
print(alist)
结果将会是:
$ python test.py
[foo, bar]
(你需要先安装multimethod这个库。)