Подтвердить что ты не робот

Python: может ли класс запретить клиентам устанавливать новые атрибуты?

Я слишком долго тратил на ошибку, как показано ниже:

>>> class Odp():
    def __init__(self):
        self.foo = "bar"


>>> o = Odp()
>>> o.raw_foo = 3 # oops - meant o.foo

У меня есть класс с атрибутом. Я пытался установить это и задавался вопросом, почему это не повлияло. Затем я вернулся к первоначальному определению класса и увидел, что атрибут был назван чем-то немного другим. Таким образом, я создавал/устанавливал новый атрибут вместо того, который имел в виду.

Во-первых, разве это не тот тип ошибки, который должны предотвращать статически типизированные языки? В этом случае в чем преимущество динамического набора текста?

Во-вторых, есть ли способ, которым я мог бы запретить это при определении Odp, и таким образом избавил себя от неприятностей?

4b9b3361

Ответ 1

Вы можете реализовать метод __setattr__ для этой цели - гораздо более надежный, чем __slots__, который часто неправильно используется для этой цели (например, __slots__ автоматически "теряется", когда класс наследуется от, а __setattr__ сохранится, если явно не переопределено).

def __setattr__(self, name, value):
  if hasattr(self, name):
    object.__setattr__(self, name, value)
  else:
    raise TypeError('Cannot set name %r on object of type %s' % (
                    name, self.__class__.__name__))

Вам нужно убедиться, что hasattr успешно используется для имен, которые вы хотите установить, например, путем установки атрибутов на уровне класса или с помощью object.__setattr__ в вашем методе __init__ чем прямое назначение атрибута. (Чтобы запретить установку атрибутов в классе, а не в экземплярах, вам придется определить настраиваемый метакласс с аналогичным специальным методом).