Наследование поведения для set и frozenset кажется различным

Может ли кто-нибудь объяснить следующее поведение:

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 

Удивительно, что вы можете изменить конструктор замороженного набора, тогда как конструктор изменяемого множества невозможно.

    Из документации Python :

    Если __new__() возвращает экземпляр cls , то метод __init__ () нового экземпляра будет вызван как __init__(self[, ...]) , где self – это новый экземпляр, а остальные аргументы – те же, что были переданы __new__() .

    set.__init__ принимает только один аргумент, итерабельность, определяющая исходное содержимое набора. Поэтому вы должны добавить свой собственный инициализатор, который принимает все дополнительные аргументы и поставляет их в качестве начальных заданных значений:

     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 действительно frozenset от кэширования объектов, то есть интерпретатору Python нужен только один экземпляр frozenset для двух объектов frozenset с тем же содержимым.

    В общем, вы должны воздерживаться от подклассификации встроенных классов, особенно если ваша семантика несовместима (в этом случае set([]) и derivedset2([]) возвращают совершенно разные результаты).