Cómo escribir métodos del mismo nombre con diferentes parámetros en python

Estoy aprendiendo Python (3.x) desde un fondo de Java.

Tengo un progtwig en Python donde creo un objeto de persona y lo añado a una lista.

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

Pero por flexibilidad, también quiero poder declararlo directamente en el método addPerson, así:

 list.addPerson("John") 

El método addPerson podrá diferenciar si estoy enviando o no un objeto Person o una cadena.

En Java crearía dos métodos separados, como este:

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

No puedo descubrir cómo hacer esto en Python. Conozco una función type (), que podría usar para verificar si el parámetro es una cadena o un objeto. Sin embargo, eso me parece desordenado. ¿Hay otra forma de hacerlo?

EDITAR:

Supongo que la solución alternativa sería algo como esto (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 

Pero parece desordenado en comparación con la solución de sobrecarga en Java.

Usando la referencia apuntada por @Kevin puedes hacer algo como:

 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) 

El resultado será:

 $ python test.py [foo, bar] 

(necesitas instalar multimetod primero)

Una forma común que he usado para implementar este patrón en particular es así:

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

No sé si eso funcionará para ti o no. Desea detectar cualquier error que la Person genere aquí si lo llama con una Person existente. Probablemente sea incluso mejor si es algo como person_factory , ya que solo puede devolver el objeto existente si ya es una persona en lugar de lanzar una excepción.

Los métodos múltiples son solo diferentes en Python; Python le permite implementar casi cualquier tipo de interfaz semántica que desee, al costo de trabajo extra bajo el capó en algún lugar, y por lo general puede moverse donde este ‘en algún lugar’ es el mejor esconderlo de usted.

También … hay ventajas en esto … cosas que ves a veces en C ++ / C # / Java como esto:

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

Se puede reemplazar en Python con solo

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

(aunque C ++ y C # tienen auto ahora que puede manejar cosas como esta también, afaik).