Наследование и переопределение init в python

Я читал "погружение в Python" , и в главе о классах он дает следующий пример:

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

затем автор говорит, что если вы хотите переопределить __init__ метод, вы должны явно вызвать родителей __init__ с правильными параметрами.

  1. , что если FileInfo класс имел более одного класса предков?
    • должен ли я явно вызывать все классы предков' __init__ методами?
  2. кроме того, я должен сделать это с любым другим методом, который я хочу переопределить?

5 ответов


книга немного устарела относительно вызова подкласса-суперкласса. Он также немного устарел в отношении встроенных классов подкласса.

это выглядит так в наши дни.

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

обратите внимание на следующее.

  1. мы можем напрямую подкласс встроенных классов, как dict, list, tuple, etc.

  2. на super функция обрабатывает отслеживание суперклассов этого класса и вызов функций в них соответственно.


в каждом классе, который вам нужно наследовать, вы можете запустить цикл каждого класса, который нуждается в инициализации дочернего класса...пример, который можно скопировать, может быть лучше понят...

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

на самом деле ты не есть вызов __init__ методы базового класса (классов), но вы обычно хочу сделать это, потому что базовые классы будут делать некоторые важные инициализации, которые необходимы для работы остальных методов классов.

для других методов, это зависит от ваших намерений. Если вы просто хотите добавить что-то в поведение базовых классов, вы захотите вызвать метод базовых классов дополнительно к своему собственному коду. Если хочешь ... фундаментально Измените поведение, вы не можете вызвать метод базового класса и реализовать все функции непосредственно в производном классе.


Если класс FileInfo имеет более одного класса предков, то вы обязательно должны вызвать все их функции __init__ (). Вы также должны сделать то же самое для функции __del__ (), которая является деструктором.


Да, вы должны позвонить __init__ для каждого родительского класса. То же самое касается функций, если вы переопределяете функцию, которая существует у обоих родителей.