Наследование атрибута класса

25. Наследование атрибута класса

Условие задачи Дан родительский класс с атрибутом класса. От него наследуются два дочерних класса, в которых собственные атрибуты не объявлены. Нужно определить, какое значение будет выведено при обращении к этому атрибуту через родительский класс и через оба дочерних класса.

class Parent(object):
    x = 1

class Child1(Parent):
    pass

class Child2(Parent):
    pass

print(Parent.x, Child1.x, Child2.x)

Что будет если мы определим поле х у наследника?

Child1.x = 2
print(Parent.x, Child1.x, Child2.x)

А в случае если переопределим у класса от которого наследуемся? (При условии что код выше уже отработал)

Parent.x = 3
print(Parent.x, Child1.x, Child2.x)
Спойлеры к решению
Подсказки
  • x объявлен как атрибут класса Parent.
  • Если у дочернего класса нет собственного x, Python ищет его у родителя.
  • Child1.x = 2 не меняет Parent.x, а создаёт или переопределяет атрибут x именно у Child1.
  • После этого Child1.x уже берётся из самого Child1, а не из Parent.
  • Если затем изменить Parent.x, это повлияет на Child2.x, потому что Child2 всё ещё берёт x у родителя.
  • На Child1.x это уже не повлияет, потому что у Child1 есть собственный атрибут x.
Решение
class Parent(object):
    x = 1

class Child1(Parent):
    pass

class Child2(Parent):
    pass

print(Parent.x, Child1.x, Child2.x)

Результат:

1 1 1

У Child1 и Child2 нет собственного атрибута x, поэтому оба класса берут его у родительского класса Parent.

Дальше:

Child1.x = 2
print(Parent.x, Child1.x, Child2.x)

Результат:

1 2 1

Строка:

Child1.x = 2

не изменяет Parent.x. Она создаёт собственный атрибут x внутри класса Child1.

Поэтому:

Parent.x = 1
Child1.x = 2
Child2.x = 1

Дальше, при условии что предыдущий код уже выполнился:

Parent.x = 3
print(Parent.x, Child1.x, Child2.x)

Результат:

3 2 3

Parent.x изменился на 3.

Child2.x тоже стал 3, потому что Child2 всё ещё не имеет собственного x и берёт значение у Parent.

Child1.x остался 2, потому что у Child1 уже есть собственный атрибут x, который перекрывает родительский.