Код:
class Foo:
def __init__(self, a1):
self._att1 = a1
@property
def att1(self):
return self._att1
@att1.setter
def att1(self, a):
if not isinstance(a, int):
print("Not allowed")
else:
self._att1 = a
class Bar(Foo):
def __init__(self):
Foo.__init__(self, 100)
@Foo.att1.setter
def att1(self, a):
Foo.att1.fset(self, a * 2)
c = Bar()
print(c.att1)
c.att1 = 10
print(c.att1)
c.att1 = "some string"
Выход:
100
20
Not allowed
UPD.
Следуя совету @chepner, я решил добавить некоторые объяснения.
Когда вы используете декоратор @Foo.att1.setter
, он не работает так, как вы ожидали.
In docs Вы можете увидеть 2 примера объявления свойств: назначьте переменную класса с помощью функции property()
и используйте декоратор @property
.Оба эти метода равносильны, но сначала я нахожу гораздо более очевидным в случае демонстрации того, как работает предоставленный код.
Перепишем объявления классов с использованием функции property()
вместо декораторов:
class Foo:
def __init__(self, a1):
self._att1 = a1
def getatt1(self):
return self._att1
def setatt1(self, a):
if not isinstance(a, int):
print("Not allowed")
else:
self._att1 = a
att1 = property(getatt1, setatt1)
class Bar(Foo):
def __init__(self):
super().__init__(100)
def setatt1(self, a):
Foo.att1.fset(self, a * 2)
att1 = property(Foo.getatt1, setatt1)
Как видите, вы не переопределяете свойство, вы создаете новое с тем же именем, что и свойство теневого базового класса.Вы можете доказать это, используя этот код:
print(f"Foo.att1 is Bar.att1: {Foo.att1 is Bar.att1}")
В обоих объявлениях он вернет False
, что означает, что объекты свойств этих классов не одинаковы.