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

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

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


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

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

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

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

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__ метод, а не прямое присвоение атрибута. (Чтобы запретить установку атрибутов в классе, а не в его экземплярах, вам придется определить собственный метакласс с помощью аналогичного специального метода).

Другие вопросы по тегам