Пакет attrs Python: валидаторы после создания - PullRequest
0 голосов
/ 12 июня 2018

Пакет attrs для python предоставляет простой способ проверки переданных переменных при создании экземпляра ( пример взят со страницы attrs ):

>>> @attr.s
... class C(object):
...     x = attr.ib(validator=attr.validators.instance_of(int))
>>> C(42)
C(x=42)
>>> C("42")
Traceback (most recent call last):
   ...
TypeError: ("'x' must be <type 'int'> (got '42' that is a <type 'str'>).", Attribute(name='x', default=NOTHING, factory=NOTHING, validator=<instance_of validator for type <type 'int'>>, type=None), <type 'int'>, '42')

Это работает хорошо, как показывает сгенерированное исключение,Однако, когда я изменяю значение x после создания экземпляра, исключение не выдается:

c = C(30)
c.x = '30'

Для статических объектов это поведение может быть в порядке, но мне кажется очень опасным предполагать, что объект является статическим.Есть ли обходной путь, чтобы получить валидаторы с attrs, которые также работают после инстанцирования?

Ответы [ 2 ]

0 голосов
/ 12 июня 2018

Один из способов сохранить изменчивость таков:

@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
0 голосов
/ 12 июня 2018

В соответствии с обсуждением в потоке для attrs

Таким образом, первоначальная реализация кода проверки фактически также выполняла валидаторы при назначении.

IЯ удалил его до слияния, потому что в динамических языках, таких как Python, слишком много способов обойти это, и я лично предпочитаю не изменять мои объекты в любом случае.Следовательно, в attrs имеется широкая поддержка для замораживания классов и создания новых экземпляров с измененными атрибутами (ассоциациями).

Конечно, вы можете добавить такую ​​функцию самостоятельно, реализовав метод setattr , который вызывает ваши валидаторы всякий раз, когда выпопробуйте установить атрибут.

...