cris
Posible duplicado:
¿Cuál es una forma pitónica limpia 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, supongamos que desea definir una clase City
.
me gustaria poder decir someCity = City()
o someCity = City("Berlin")
donde el primero solo proporciona 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
mzz
Si sus firmas difieren sólo en el número de argumentos, usar argumentos predeterminados es la forma correcta de hacerlo. Si quieres poder pasar en diferentes tipos de argumento, trataría de evitar la isinstance
basado en el enfoque mencionado en otra respuesta, y en su lugar use argumentos de palabras clave.
Si usar solo argumentos de palabras clave se vuelve difícil de manejar, puede combinarlo con métodos de clase (al código bzrlib le gusta este enfoque). Este 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 from_filename(cls, name):
return cls(open(name, 'rb'))
# Now you can do:
c = C(fd)
# or:
c = C.from_filename('a filename')
Observe que todos esos métodos de clase siguen pasando por lo mismo __init__
pero usar métodos de clase puede ser mucho más conveniente que tener que recordar qué combinaciones de argumentos de palabras clave __init__
trabajar.
isinstance
es mejor evitarlo porque el tipo de pato de Python hace que sea difícil averiguar 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 subclasifican file
(como los devueltos por urllib, o StringIO, o…). Por lo general, es una mejor idea que la persona que llama le diga explícitamente a qué tipo de objeto se refería, mediante el uso de diferentes argumentos de palabras clave.
-
Como usted dice, este es un gran enfoque si necesita pasar diferentes tipos de argumentos. En esos casos tiendo a usar un muy básico
__init__
y hacer más de un método de clase para cada caso.– zekel
26/09/2016 a las 22:20
-
esta es la solución más generalmente aplicable
– Guilherme de Lázari
13 de abril de 2018 a las 14:36
-
hay una buena manera (su recomendación) para no ejecutar el habitual
__init__
función del segundo constructor? por ejemplo, porque ambos construirán el objeto desde cero– ThorSummoner
23 de abril de 2019 a las 22:21
pavpanchekha
Para el ejemplo que diste, usa los valores predeterminados:
class City:
def __init__(self, name="Default City Name"):
...
...
En general, tienes dos opciones:
-
Hacer
if
–elif
bloques basados en el tipo:def __init__(self, name): if isinstance(name, str): # todo elif isinstance(name, City): # todo # todo
-
Use la tipificación 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.
Telliott99
La respuesta de Jack M. es correcta. Hacerlo de esta forma:
>>> 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
>>>
jack m
La forma más fácil es a través de argumentos de palabras clave:
class City():
def __init__(self, city=None):
pass
someCity = City(city="Berlin")
Esto es algo bastante básico. tal vez mira la documentación de Python?
-
errores tipográficos en los comentarios; Además, esa no es la pregunta que hizo: preguntó sobre cambiar tipos, solo proporcionó un mal ejemplo.
– pavpanchekha
29 de enero de 2010 a las 18:42
-
@pavpanchekha: es exactamente lo que se preguntó. excepto por supuesto que falta
self
.– Fantasma silencioso
29 de enero de 2010 a las 18:43
-
@Jack, tu ejemplo en realidad no almacena
city
en cualquier lugar tampoco, por lo que para un novato esta podría ser una respuesta bastante confusa.–Peter Hansen
29 de enero de 2010 a las 19:30
-
errores tipográficos en los comentarios; Además, esa no es la pregunta que hizo: preguntó sobre cambiar tipos, solo proporcionó un mal ejemplo.
– pavpanchekha
29 de enero de 2010 a las 18:42
-
@pavpanchekha: es exactamente lo que se preguntó. excepto por supuesto que falta
self
.– Fantasma silencioso
29 de enero de 2010 a las 18:43
-
@Jack, tu ejemplo en realidad no almacena
city
en cualquier lugar tampoco, por lo que para un novato esta podría ser una respuesta bastante confusa.–Peter Hansen
29 de enero de 2010 a las 19:30
Hazme pensar en esta pregunta – stackoverflow.com/questions/682504/…
– Gante
29 de enero de 2010 a las 18:49
Lo mejor: cómo sobrecargar
__init__
método basado en el tipo de argumento?–Bob Stein
30 de junio de 2017 a las 1:52
Esta pregunta es engañosa en base a la relación del título y el cuerpo. Peor aún, parece ser la respuesta principal en Google; Desearía que se editara o eliminara, ya que la pregunta en el cuerpo es realmente básica. Las respuestas al título se pueden encontrar en el posible enlace duplicado.
– John Smith
23 de julio de 2019 a las 14:57