Varios constructores en python? [duplicar]


Posible Duplicado:
¿Qué es una forma limpia y pitónica de tener múltiples constructores en Python?

No Es posible definir varios 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 gustaría poder decir someCity = City() o someCity = City("Berlin"), donde el primero solo da un valor de nombre predeterminado, y el segundo define se.

Author: Community, 2010-01-29

5 answers

A diferencia de Java, no se pueden definir varios constructores. Sin embargo, puede definir un valor predeterminado si no se pasa uno.

def __init__(self, city="Berlin"):
  self.city = city
 188
Author: Andrew Sledge,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-29 18:41:42

Si sus firmas difieren solo en el número de argumentos usar argumentos predeterminados es la forma correcta de hacerlo. Si desea poder pasar diferentes tipos de argumento, trataría de evitar el enfoque basado en isinstance mencionado en otra respuesta, en lugar de usar argumentos de palabras clave. Si usar solo argumentos de palabras 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 consigas el 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 esos métodos de clase siguen pasando por el 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 funcionan para __init__.

isinstance es mejor evitar porque el duck typing 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 lo hacen subclase file (como las devueltas desde urllib, o StringIO, o...). Por lo general, es mejor que la persona que llama le diga explícitamente a qué tipo de objeto se refería, utilizando diferentes argumentos de palabras clave.

 165
Author: mzz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-11 17:41:40

Para el ejemplo que dio, use los valores predeterminados:

class City:
    def __init__(self, name="Default City Name"):
        ...
    ...

En general, tienes dos opciones:

1) Do if-elif bloques basados en el tipo:

def __init__(self, name):
    if isinstance(name, str):
        ...
    elif isinstance(name, City):
        ...
    ...

2) Use duck typing --- es decir, asuma que el usuario de su clase es lo suficientemente inteligente como para usarla correctamente. Esta es normalmente la opción preferida.

 3
Author: pavpanchekha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-28 00:45:12

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

>>>
 2
Author: telliott99,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-29 19:00:39

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 bastante básico, tal vez mirar los documentos de python?

 1
Author: Jack M.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-29 19:23:04