Я получаю ошибку Can't set attribute
, когда я использую оператор +=
для свойства только для чтения, которое имеет тип, для которого я определил метод __iadd__()
.Как использовать оператор + = для свойства, которое не имеет сеттера?
упрощенные (но работоспособные) версия моего кода:
class Emitter(list):
def __iadd__(self, other):
self.append(other)
return self
class Widget:
def __init__(self):
self._on_mouseenter = Emitter()
@property
def on_mouseenter(self): return self._on_mouseenter
my_widget = Widget()
my_widget.on_mouseenter += lambda source: print("on_mouseenter!")
Последняя строка выдает ошибку. Она уходит, если добавить следующую строку в определении Widget
:
@on_mouseenter.setter
def on_mouseenter(self, value): pass
(Runnable в https://repl.it/EONf/0)
Такое поведение кажется странным на два счета. Во-первых, я думал, что Python передает объекты по ссылке, так почему же свойство должно быть читаемым? И, во-вторых, как получилось, что мой фиктивный сеттер работает?
Ответы объясняют проблему, однако вы можете просто определить 'self.on_mouseenter = Emitter()' непосредственно и избежать свойства. –
Будьте осторожны с вашей терминологией. В то время как Python передает ссылки на объекты, «pass by reference» относится к чему-то тонко другому. У Python действительно нет хорошего стандартного имени; некоторые люди называют это «вызовом по объекту», «вызовом путем совместного использования» или, как говорят люди Java, «передать по значению, но переданное значение является ссылкой». – user2357112
@BenHoyt: Я хотел сделать свойство доступным только для чтения, чтобы код пользователя не мог его перезаписать. Это антипаттерн в Python? – JPNotADragon