Потому что вы называете это непоследовательно - один раз напрямую, а один раз через свойство. Измените self._set_x(x)
в Parent.__init__
на self.x = x
, и вы увидите, что Child._set_x
никогда не вызывается. Чтобы переопределить сеттер в дочернем классе, вы можете использовать property.setter
в качестве декоратора:
class Child(Parent):
@Parent.x.setter
def x(self, arg):
super()._set_x(arg)
Или добавить уровень косвенности к свойству:
class Parent(object):
# ...
x = property(
lambda self: self._get_x(),
lambda self, x: self._set_x(x)
)
Переопределение не работает напрямую, потому что свойство хранит конкретные объекты методов (Parent._get_x
и Parent._set_x
) и не ищет их снова, даже если тип объекта изменяется - код, который работает одинаково независимо. Поиск сил косвенного действия в динамическом типе self
, который допускает переопределение.