Наследование в Python3: AttributeError: ‘Atom’ object has no attribute ‘_Base__setProperties’

380 просмотра
0
0 Комментариев

Есть простой базовый класс Base:

class Base(object):
    def __init__(self):
        self.__setProperties = dict()
        self.__setProperties['className'] = 'Base'
 
    def updateProperty(self, propertyName, propertyValue):
        self.__setProperties[propertyName] = propertyValue

Когда наследуюсь от QWidget и от Base вот так

class MainWidget(QWidget, Base):
    def __init__(self):
        QWidget.__init__(self)
        self.__setProperties = dict()
        self.updateProperty('className', 'MainWidget')

экземпляр класса MainWidget создать получается. Когда же наследуюсь просто от класса Base вот так:

class Atom(Base):
    def __init__(self):
        self.__setProperties = dict()
        self.updateProperty('className', 'Atom')

при попытке создания экземпляра класса Atom возникает ошибка:

AttributeError: 'Atom' object has no attribute '_Base__setProperties'

Подскажите, пожалуйста, в чём дело.

UPD:
Если сделать так (поменять порядок QWidget, Base на Base, QWidget):

class MainWidget(Base, QWidget):

То возникает ошибка:

AttributeError: 'MainWidget' object has no attribute '_Base__setProperties'


Добавить комментарий

1 Ответы

Python Опубликовано 09.12.2018
0

Имена начинающиеся на __ являются частными для класса. Метод Base.updateProperty() использует __setProperties атрибут, который не определён при вызове из Atom класса (базовый __init__ не вызван).

В варианте с QWidget.__init__(self) не было ошибки, так это метод неявно Base.__init__() вызвал (следуя MainWidget.mro()).

Если при наследовании использовать Base, QWidget порядок классов, то QWidget станет идти после Base in MainWidget.mro(), поэтому QWidget.__init__(self) в этом случае не вызывает Base.__init__() и снова AttributeError возникает.

Пример, демонстрирующий порядок вызовов:

#!/usr/bin/env python3
 
class A:
    def __init__(self, a, **kwargs):
        print('A', a)
        super().__init__(**kwargs)
 
class B:
    def __init__(self, b, **kwargs):
        print('B', b)
        super().__init__(**kwargs)
 
class C(A, B):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
 
class D(B, A):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
 
 
C(a=1, b=2)
D(a=10, b=20)

Результат:

A 1
B 2
B 20
A 10

Один вызов super().__init__(**kwargs) в С привёл к вызову A.__init__(), B.__init__() и в обратном порядке для D. В зависимости от цепочки наследования A.__init__ может вызвать B.__init__ и наоборот. Это зависит от C.mro() и D.mro():

print(C.mro())
print(D.mro())

Результат:

[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]

Связанный вопрос: Классы, наследование, атрибуты в python

Добавить комментарий
Напишите свой ответ на данный вопрос.
Scroll Up