Herencia y Sobreescritura init en python


Estaba leyendo 'Dive Into Python' y en el capítulo sobre clases da este ejemplo:

class FileInfo(UserDict):
    "store file metadata"
    def __init__(self, filename=None):
        UserDict.__init__(self)
        self["name"] = filename

El autor entonces dice que si desea sobrescribir el método __init__, debe llamar explícitamente al padre __init__ con los parámetros correctos.

  1. ¿Y si esa clase FileInfo tuviera más de una clase de antepasado?
    • ¿Tengo que llamar explícitamente a todos los métodos __init__ de las clases antecesoras?
  2. También, tengo que hacer esto a cualquier otro método I desea anular?
Author: Eugene S, 2009-04-16

5 answers

El libro está un poco anticuado con respecto a las llamadas subclase-superclase. También es un poco anticuado con respecto a las clases integradas de subclases.

Se ve así hoy en día.

class FileInfo(dict):
    """store file metadata"""
    def __init__(self, filename=None):
        super( FileInfo, self ).__init__()
        self["name"] = filename

Tenga en cuenta lo siguiente.

  1. Podemos subclase directamente clases integradas, como dict, list, tuple, etc.

  2. La función super se encarga de rastrear las superclases de esta clase y llamar a las funciones en ellas apropiadamente.

 137
Author: S.Lott,
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
2009-04-15 20:49:52

En cada clase de la que necesita heredar, puede ejecutar un bucle de cada clase que necesita iniciarlo al iniciar el hijo class...an ejemplo que se puede copiar podría ser mejor entendido...

class Female_Grandparent:
    def __init__(self):
        self.grandma_name = 'Grandma'

class Male_Grandparent:
    def __init__(self):
        self.grandpa_name = 'Grandpa'

class Parent(Female_Grandparent, Male_Grandparent):
    def __init__(self):
        Female_Grandparent.__init__(self)
        Male_Grandparent.__init__(self)

        self.parent_name = 'Parent Class'

class Child(Parent):
    def __init__(self):
        Parent.__init__(self)
#---------------------------------------------------------------------------------------#
        for cls in Parent.__bases__: # This block grabs the classes of the child
             cls.__init__(self)      # class (which is named 'Parent' in this case), 
                                     # and iterates through them, initiating each one.
                                     # The result is that each parent, of each child,
                                     # is automatically handled upon initiation of the 
                                     # dependent class. WOOT WOOT! :D
#---------------------------------------------------------------------------------------#



g = Female_Grandparent()
print g.grandma_name

p = Parent()
print p.grandma_name

child = Child()

print child.grandma_name
 16
Author: Code Bug,
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
2014-04-30 22:20:05

Realmente no tiene para llamar a los métodos __init__ de la(s) clase (s) base, pero normalmente quiere hacerlo porque las clases base harán algunas inicializaciones importantes allí que son necesarias para que el resto de los métodos de las clases funcionen.

Para otros métodos depende de sus intenciones. Si solo desea agregar algo al comportamiento de las clases base, querrá llamar al método clases base adicionalmente a su propio código. Si desea cambiar fundamentalmente la comportamiento, es posible que no llame al método de la clase base e implemente toda la funcionalidad directamente en la clase derivada.

 12
Author: sth,
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
2009-04-15 21:00:40

Si la clase FileInfo tiene más de una clase ancestro entonces definitivamente deberías llamar a todas sus funciones __init__ (). También deberías hacer lo mismo con la función __del__ (), que es un destructor.

 4
Author: marcog,
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
2009-04-15 20:49:08

Sí, debe llamar a __init__ para cada clase padre. Lo mismo ocurre con las funciones, si está sobreescribiendo una función que existe en ambos padres.

 2
Author: vezult,
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
2009-04-15 20:50:35