multiple inheritance python
¿Múltiples constructores en python? (5)
Posible duplicado:
¿Cuál es una forma limpia y pitónica de tener múltiples constructores en Python?
¿No es posible definir múltiples constructores en Python, con diferentes firmas? Si no, ¿cuál es la forma general de evitarlo?
Por ejemplo, digamos que quería definir una clase City
Me gustaría poder decir someCity = City()
o someCity = City("Berlin")
, donde el primero solo da un valor de nombre predeterminado, y el segundo lo define.
A diferencia de Java, no puede definir múltiples constructores. Sin embargo, puede definir un valor predeterminado si no se pasa uno.
def __init__(self, city="Berlin"):
self.city = city
Jack M. tiene razón, hazlo de esta manera:
>>> class City:
... def __init__(self, city=None):
... self.city = city
... def __repr__(self):
... if self.city: return self.city
... return ''''
...
>>> c = City(''Berlin'')
>>> print c
Berlin
>>> c = City()
>>> print c
>>>
La manera más fácil es a través de argumentos de palabra clave:
class City():
def __init__(self, city=None):
pass
someCity = City(city="Berlin")
Esto es bastante básico, ¿tal vez mirar los documentos de Python ?
Para el ejemplo que dio, use valores predeterminados:
class City:
def __init__(self, name="Default City Name"):
...
...
En general, tienes dos opciones:
1) Hacer if
- bloques elif
basados en el tipo:
def __init__(self, name):
if isinstance(name, str):
...
elif isinstance(name, City):
...
...
2) Use el tipado de pato, es decir, suponga que el usuario de su clase es lo suficientemente inteligente como para usarlo correctamente. Esta suele ser la opción preferida.
Si sus firmas difieren solo en el número de argumentos que usan argumentos predeterminados, es la forma correcta de hacerlo. Si desea poder pasar diferentes tipos de argumentos, trataría de evitar el isinstance
basado en la isinstance
mencionado en otra respuesta, en lugar de usar argumentos de palabra clave. Si el uso de solo argumentos de palabra clave se vuelve difícil de manejar, puede combinarlo con classmethods (al código bzrlib le gusta este enfoque). Esto es solo un ejemplo tonto, pero espero que entiendas la idea:
class C(object):
def __init__(self, fd):
# Assume fd is a file-like object.
self.fd = fd
@classmethod
def fromfilename(cls, name):
return cls(open(name, ''rb''))
# Now you can do:
c = C(fd)
# or:
c = C.fromfilename(''a filename'')
Observe que todos los métodos de clase aún pasan por el mismo __init__
, pero el uso de métodos de clase puede ser mucho más conveniente que tener que recordar qué combinaciones de argumentos de palabra clave funcionan para __init__
.
Es mejor evitar la isinstance
porque el isinstance
de pato de python hace difícil determinar qué tipo de objeto se pasó realmente. Por ejemplo: si desea tomar un nombre de archivo o un objeto similar a un archivo, no puede usar isinstance(arg, file)
porque hay muchos objetos similares a archivos que no incluyen archivos de subclase (como los devueltos desde urllib, o StringIO, o ...). Por lo general, es una mejor idea que la persona que llama le diga explícitamente qué tipo de objeto significa, utilizando diferentes argumentos de palabras clave.