为什么只在新样式类中使用object .__ setattr __(self,name,value)?

时间:2016-07-31 08:48:04

标签: python class inheritance setattr new-style-class

根据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__方法,但经典类也可以从基类继承。那么为什么只推荐新款式?

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

1 个答案:

答案 0 :(得分:3)

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

来自documentation on slots

  

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

     

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

通过在类上添加data descriptors来实现对插槽的访问;每个此类属性都有__set__和/或__del__方法的对象。

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

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