Python:类可以禁止客户端设置新属性吗?

Nic*_*ner 12 python oop typing

我只是花了太长时间来处理如下错误:

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


>>> o = Odp()
>>> o.raw_foo = 3 # oops - meant o.foo
Run Code Online (Sandbox Code Playgroud)

我有一个属性的类.我试图设置它,并想知道它为什么没有效果.然后,我回到原始的类定义,并看到该属性被命名为稍微不同的东西.因此,我正在创建/设置一个新属性而不是那个属性.

首先,这不是静态类型语言应该阻止的错误类型吗?在这种情况下,动态类型的优势是什么?

其次,有没有一种方法可以在定义时禁止它Odp,从而为自己省去了麻烦?

Ale*_*lli 21

您可以__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__))
Run Code Online (Sandbox Code Playgroud)

你必须确保hasattr成功,你的名字希望能够通过在类级别设置的属性或通过使用来设定,例如object.__setattr__在你的__init__方法,而不是直接的属性分配.(要禁止在而不是其实例上设置属性,您必须使用类似的特殊方法定义自定义元类).

  • "不支持XX赋值"消息(例如对于项目)使用`TypeError`,更令人困惑的措辞"没有属性XX"使用`AttributeError`,所以我猜两者都可以(尽管两者都不完美). (2认同)