I am recently writing a batch of customized container classes which are mostly inherited from built-in list
, dict
and set
types, and I surprising encountered an error, a class inherited from built-in set
will raise exception when copied using copy
module’s copy
and deepcopy
function, while other classes works fine.
The traceback message is like:
TypeError: SetBase.__init__() missing 2 required positional arguments: 'name' and 'master'
SetBase
is the class inherited from built-in set
class, and it takes two more arguments name and master in __init__
method.
I Googled around and finally locate the cause of error lies in the __reduce_ex__
method of set
.
Then I tried this:
>>> "".__reduce_ex__(5)
(<function __newobj__ at 0x104d41800>, (<class 'str'>, ''), None, None, None)
>>> [].__reduce_ex__(5)
(<function __newobj__ at 0x104d41800>, (<class 'list'>,), None, <list_iterator object at 0x104c43df0>, None)
>>> {1:1}.__reduce_ex__(5)
(<function __newobj__ at 0x104d41800>, (<class 'dict'>,), None, None, <dict_itemiterator object at 0x104c5f830>)
>>> (1,2).__reduce_ex__(5)
(<function __newobj__ at 0x104d41800>, (<class 'tuple'>, (1, 2)), None, None, None)
>>> {1,2}.__reduce_ex__(5)
(<class 'set'>, ([1, 2],), None)
I got a general knowledge that list
, dict
, tuple
use __newobj__
function to create a copied instance while set
is not, it uses set
class.
My class derived from set
class follows the pattern, so it explicitly calls the __init__
method after a copied instance is created. As the args are not fully given, an exception is raised.
My question is what makes set
so different in terms of __reduce_ex__
method?