Автор Тема: Вызов конструкторов родителей при множественном наследовании  (Прочитано 17783 раз)

DigitalMag

  • Юный джедай
  • **
  • Сообщений: 89
  • Репутация +6/-0
    • Просмотр профиля
У меня есть класс:

class HTMLMixin:

    def __init__(self, sub = 'def', cssclass = '', *args, **kwargs):                 # request=None,

        super(HTMLForm, self).__init__(*args, **kwargs)

        self.request = kwargs.pop('request', None)       
        self.submit = sub
        self.css_class = cssclass
        self.enctype = kwargs.get('enctype','')

Я от него наследуюсь:

class SignForm(AuthenticationForm, HTMLMixin):
    pass
Но получаю ошибку
Цитата:
'SignForm' object has no attribute 'css_class'
. Получается, что SignForm не вызывает конструктор HTMLMixin автоматически?

« Последнее редактирование: Марта 30, 2019, 11:22:39 am от DigitalMag »

AdminUser

  • Team Lead
  • Юный джедай
  • *****
  • Сообщений: 65
  • Репутация +8/-0
    • Просмотр профиля
В python если вы в конструкторе не переопределяете конструктор вручную, будет автоматически вызван конструктор родителя первой ветки наследования. И далее согласно последовательности __mro__. Единственное, что может вам помешать вызвать конструктор родителя - это его переопределение в классе-предке без вызова конструктора-предка, например:

class A(object): pass

class B(object):
    def __init__(self):
        self.b = 1
        print "bbbbbbbbbbb"

class C(A,B):
    def __init__(self):
        super(C,self).__init__()
        print "cccccccccccc"
        #print self.a
        print self.b

def main():
    c = C()

выведет:

Цитата:
bbbbbbbbbbb
cccccccccccc
1
Но если мы переопределим конструктор в A без вызова super:

class A(object):
    def __init__(self):
        pass

то получим ошибку:

Цитата:
AttributeError: 'C' object has no attribute 'b'      
      

Если же переопределить грамотно:

class A(object):
    def __init__(self):
        super(A,self).__init__()
        print "AAAAAAAAAAAAA"

то все конструкторы вызовутся по порядку без ошибок.

Так же для 2.7 важно, чтобы все объекты в цепочке mro были наследованы от object - т.е. их классы были типами, а не  экземплярами classobj. О чем я говорю:

class B:
    def __init__(self):

        self.b = 1
        print "BBBBBBBBBBBB"

Наследование от такого класса не будет вызывать его конструктор, т.е. наследует только атрибуты класса - все методы и поля класса, но не экземпляра. Это тоже важный паттерн
« Последнее редактирование: Марта 30, 2019, 12:10:05 pm от AdminUser »

DigitalMag

  • Юный джедай
  • **
  • Сообщений: 89
  • Репутация +6/-0
    • Просмотр профиля
Сделал HTMLMixin типом:

class HTMLMixin(object):Но все равно не видит поля css_class

Если поменять их местами, то получаю ошибку на строке:

super(SignForm, self).__init__(*args, **kwargs)
Цитата:
super(type, obj): obj must be an instance or subtype of type

Сам конструктор HTMLMixin вызывается, но при попытке вызвать из него конструктор родителя получаю такую ошибку
« Последнее редактирование: Марта 30, 2019, 12:20:39 pm от AdminUser »

AdminUser

  • Team Lead
  • Юный джедай
  • *****
  • Сообщений: 65
  • Репутация +8/-0
    • Просмотр профиля
Цитата:
Но все равно не видит поля css_class

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

Поэтому вам надо использовать class SignForm(HTMLMixin, AuthenticationForm):
Что касается другой ошибки, то я внимательно посмотрел ваш код и нашел в нем такую ошибку: ваш класс называется HTMLMixin, а в конструкторе вы вызываете HTMLForm. Это, вероятно, просто ваша опечатка.

« Последнее редактирование: Марта 30, 2019, 12:45:09 pm от AdminUser »

DigitalMag

  • Юный джедай
  • **
  • Сообщений: 89
  • Репутация +6/-0
    • Просмотр профиля