Унаследованное поведение для набора и Frozenset, кажется, отличается - PullRequest
7 голосов
/ 31 января 2011

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

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

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

1 Ответ

4 голосов
/ 31 января 2011

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

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

...