How to write same-name methods with different parameters in python [duplicate]

余生颓废 提交于 2019-12-09 10:40:30

问题


I'm learning Python (3.x) from a Java background.

I have a python program where I create a personObject and add it to a list.

p = Person("John")
list.addPerson(p)

But for flexibility I also want to be able to declare it directly in the addPerson method, like so:

list.addPerson("John")

The addPerson method will be able to differentiate whether or not I'm sending a Person-object or a String.

In Java I would create two separate methods, like this:

void addPerson(Person p) {
    //Add person to list
}

void addPerson(String personName) {
    //Create Person object
    //Add person to list
}

I'm not able to find out how to do this in Python. I know of a type() function, which I could use to check whether or not the parameter is a String or an Object. However, that seems messy to me. Is there another way of doing it?

EDIT:

I guess the alternative workaround would be something like this(python):

def addPerson(self, person):
    //check if person is string
        //Create person object

    //Check that person is a Person instance
        //Do nothing

    //Add person to list

But it seems messy compared to the overloading solution in Java.


回答1:


Using the reference pointed by @Kevin you can do something like:

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)

The result will be:

$ python test.py
[foo, bar]

(you need to install multimethod first)




回答2:


One common way I've used to implement this particular pattern is like this:

def first(self, person):
    try:
        person = Person(person)
    except ConstructionError as e: 
        pass
    # do your thing

I don't know if that will work for you or not. You want to catch whatever error Person would generate here if you call it with an existing Person. It's probably even better if that's something like person_factory, as it can just return the existing object if it's already a person instead of throwing an exception.

Multimethods are just different in Python; Python lets you implement almost any kind of semantic interface you want, at the cost of extra work under the hood somewhere, and you can usually move around where this 'somewhere' is to best hide it from you.

Also... there are advantages to this... things that you see sometimes in C++/C#/Java like this:

 int sum(int a, int b) {
     return (a+b)
 }
 float sum (float a, float b) {
     return (a+b)
 }
 etc.

can be replaced in python with just

 def sum(a,b):
      return a+b

(though C++ and C# have auto now that can handle things like this too, afaik).



来源:https://stackoverflow.com/questions/22377338/how-to-write-same-name-methods-with-different-parameters-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!