2016-07-31 42 views
0

根据Python的2.7.12文档:为什么只在新样式类中偏爱object .__ setattr __(self,name,value)?

如果__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

*那么为什么只推荐用于新样式类?*调用'__setattr__'而不是直接在实例字典上操作允许超类对发生的事情进行“监督”。将这种方法看作是新风格类别的优势。它可能会被推荐用于所有类,但不能继承*的旧式类没有可调用'__setattr__'方法的超类。 – jedwards

+1

@jedwards是的,因为经典类没有'classobj .__ setattr__',只有'object .__ setattr__'用于新样式类。 –

+0

你完全正确。我想说的是,我认为你把加粗的那句话,没有这么多来自字典,直接使用实例挫折(如你表明,它工作在很多情况下完全正常,并作为马亭显示,存在这样的情况也不会),但更多的鼓励*使用'__setattr__',这允许超类有些监督和使用诸如描述符之类的新特征。对不起,如果我不清楚:) – jedwards

回答

3

新样式类可以使用,此时不存在要指定的__dict__。新样式类别还支持其他数据描述符,该类定义在处理某些名称的属性设置或删除的类上。

documentation on slots

默认情况下,新老风格的类的实例有一个字典属性存储。这浪费了具有很少实例变量的对象的空间。创建大量实例时,空间消耗可能会变得尖锐。

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

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

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

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

+0

也许“在'__dict__'中为这样的对象设置一个键将被忽略”应该是“为其__dict__中的类使用数据描述符的对象设置键将被忽略”to让它更清晰? –

+0

@sunqingyao:所讨论的'对象'是类中的数据描述符。 –

相关问题