Inheriting behaviours for set and frozenset seem to differ

Can someone explain the following behaviour:

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

This is surprising to me that you can alter the constructor of a frozen set whereas it is not possible for the constructor of a mutable set.


From the Python documentation:

If __new__() returns an instance of cls , then the new instance's __init__ () method will be invoked like __init__(self[, ...]) , where self is the new instance and the remaining arguments are the same as were passed to __new__() .

set.__init__ only takes one argument, an iterable specifying the initial set contents. Therefore, you should add your own initializer which takes all additional arguments and supplies them as the initial set values:

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

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

Notice that you should overwrite __init__ and refrain from implementing __new__ unless you want to implement object caching, singletons, or similar weird stuff. Your subclassing works for frozenset precisely because frozenset does profit from object caching, ie the Python interpreter only needs one frozenset instance for two frozenset objects with the same content.

In general, you should refrain from sub-classing built-in classes, especially if your semantics are incompatible (in this case, set([]) and derivedset2([]) return totally different results).

链接地址: http://www.djcxy.com/p/50458.html

上一篇: 匹配算法

下一篇: 继承set和frozenset的行为似乎有所不同