0

根据 Python 2.7.12 文档:

如果__setattr__()要分配给实例属性,它不应该简单地执行self.name = value——这将导致对自身的递归调用。相反,它应该在实例属性字典中插入值,例如self.__dict__[name] = value. 对于新式类,它应该调用具有相同名称的基类方法,而不是访问实例字典,例如, object.__setattr__(self, name, value) .

但是,以下代码可以按预期工作:

class Class(object):
    def __setattr__(self, name, val):
        self.__dict__[name] = val;

c = Class()
c.val = 42
print c.val

我知道super(Class, obj).__setattr__(name, value)可以确保__setattr__所有基类的方法都被调用,但是经典类也可以从基类继承。那么为什么只推荐用于新风格课程呢?

或者,另一方面,为什么不推荐经典课程这样做?

4

1 回答 1

4

新型类可能正在使用slot,此时没有__dict__可分配的。新型类还支持其他数据描述符,在类上定义的对象,用于处理某些名称的属性设置或删除。

有关插槽的文档中

默认情况下,新旧类的实例都有一个用于属性存储的字典。这浪费了具有很少实例变量的对象的空间。创建大量实例时,空间消耗会变得很严重。

__slots__可以通过在新样式的类定义中定义来覆盖默认值。该__slots__声明采用一系列实例变量,并在每个实例中保留足够的空间来保存每个变量的值。__dict__因为不是为每个实例创建空间,所以节省了空间。

对插槽的访问是通过在类上添加数据描述符来实现的;每个此类属性具有__set__和/或__del__方法的对象。

数据描述符的另一个示例是附加了 setter 或 deleter 函数的property()对象。在 中设置与这样的描述符对象同名的键__dict__将被忽略,因为数据描述符会导致属性查找完全绕过__dict__

object.__setattr__()知道如何处理数据描述符,这就是为什么你应该调用它。

于 2016-07-31T08:55:21.367 回答