set和frozenset的继承行为似乎有所不同

时间:2011-01-31 11:32:32

标签: python inheritance immutability built-in-types

有人可以解释以下行为:

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 个答案:

答案 0 :(得分:4)

来自Python documentation

  

如果__new__()返回cls的实例,则会调用新实例的__init__()方法,如__init__(self[, ...]),其中self是新的实例和其余参数与传递给__new__()的参数相同。

set.__init__只接受一个参数,一个指定初始设置内容的iterable。因此,您应该添加自己的初始化程序,它接受所有其他参数并将它们作为初始设置值提供:

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,因为frozenset 确实从对象缓存中获利,即Python解释器只需要一个frozenset实例用于两个frozenset个对象具有相同的内容。

通常,您应该避免对内置类进行子类化,特别是如果您的语义不兼容(在这种情况下,set([])derivedset2([])会返回完全不同的结果)。