如何在Python中编写参数不同的同名方法

11 投票
2 回答
17267 浏览
提问于 2025-04-17 22:06

我正在学习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这个库。)

撰写回答