Один из способов сохранить изменчивость таков:
@attr.s
class C(object):
_x = attr.ib(validator=attr.validators.instance_of(int))
@property
def x(self):
return self._x
@x.setter
def x(self, value):
assert isinstance(value, int), repr(value) # or whatever error you want
self._x = value
Но даже это не безопасно для c._x = '30'
.
Проблема не в attrs
, а впитон.a.b = c
всегда будет работать, когда a.b
это просто переменная.Это происходит из-за концепции питонов «мы все взрослые по соглашению» - то есть все публично, и все модифицируемо.Если вы редактируете что-то, что не должны делать, это ваша вина.
При этом attrs
предоставляет взлом для предотвращения присвоения атрибута, чтобы создать иллюзию неизменности:
@attr.s(frozen=True)
class C(object):
x = attr.ib(validator=attr.validators.instance_of(int))
c = C(1)
c.x = 30 # raises FrozenInstanceError