2011-01-31 48 views
7

有人可以解释以下行为:对于设置和frozenset继承行为似乎有所不同

class derivedset1(frozenset): 
    def __new__(cls,*args): 
     return frozenset.__new__(cls,args) 

class derivedset2(set): 
    def __new__(cls,*args): 
     return set.__new__(cls,args)  

a=derivedset1('item1','item2') # WORKS 
b=derivedset2('item1','item2') # DOESN'T WORK 

Traceback (most recent call last): 
    File "inheriting-behaviours.py", line 12, in <module> 
    b=derivedset2('item1','item2') # DOESN'T WORK 
TypeError: derivedset2 expected at most 1 arguments, got 2 

这是令人惊讶的,我认为你可以改变冷冻集的构造函数,而这是不可能的构造一个可变的集合。

+1

有趣的数据点:`b = derivedset2(['item1','item2'])`工作。 – 2011-01-31 11:45:42

回答

4

从:

如果__new__()回报cls,然后实例的新实例的__init__()方法将被调用像__init__(self[, ...]),其中self是新实例,其余参数都一样被传递给__new__()

set.__init__只需要一个参数,一个指定初始设置内容的迭代器。因此,你应该添加自己的初始化这需要所有的附加参数,并将其提供作为初始设定值:

class derivedset2(set): 
    def __new__(cls,*args): 
     return set.__new__(cls,*args) 

    def __init__(self, *initial_values): 
     set.__init__(self, initial_values) 

请注意,您应该覆盖__init__,除非你想实现对象缓存从执行__new__避免,单身,或类似的奇怪的东西。因为frozenset确实是利润来自对象缓存,即Python解释器只需要一个frozenset实例用于具有相同内容的两个frozenset对象,您的子类化适用于frozenset

一般来说,您应该避免对内置类进行子分类,尤其是在语义不兼容的情况下(在这种情况下,set([])derivedset2([])会返回完全不同的结果)。

+3

'frozenset`使用`__new__`的原因不是缓存,而是因为它是不可变的。如果这些元素被`__init__`消耗了,那么这个类将不得不有点可变。然后`fs = frozenset .__ new __(frozenset)`会创建一个空的`frozenset`,可以用`fs .__ init __([1,2,3])`填充(变异)。这在子类化过程中每次都会发生。 – 2011-01-31 12:27:20

相关问题