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 ofcls, then the new instance’s__init__() method will be invoked like__init__(self[, ...]), whereselfis 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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With