Inheriting behaviours for set and frozenset seem to differ
Can someone e开发者_StackOverflow中文版xplain 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 ofcls
, then the new instance’s__init__
() method will be invoked like__init__(self[, ...])
, whereself
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, i.e. 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).
精彩评论