Python: Как я могу наследовать из встроенного типа списка?

Вопрос:Я хочу добавить некоторые атрибуты к встроенному типу list, поэтому я написал это: class MyList(list): def __new__(cls, *args, **kwargs): obj = super(MyList, cls).__new__(cls, *args, **kwargs) obj.append('FirstMen') return obj def __init__(self, *args, **kwargs): self.name = 'Westeros' def king(self): print 'IronThrone' if __name__ == '__main__': my_list = MyList([1, 2, 3, 4]) print my_list но my_list содержит только

Вопрос:

Я хочу добавить некоторые атрибуты к встроенному типу list, поэтому я написал это:

class MyList(list): def __new__(cls, *args, **kwargs): obj = super(MyList, cls).__new__(cls, *args, **kwargs) obj.append(‘FirstMen’) return obj def __init__(self, *args, **kwargs): self.name = ‘Westeros’ def king(self): print ‘IronThrone’ if __name__ == ‘__main__’: my_list = MyList([1, 2, 3, 4]) print my_list

но my_list содержит только элемент ‘FirstMen’. Почему мой __new__ здесь не работает? И как мне наследовать от встроенного типа типа list? То же самое для неизменяемых типов, таких как str?

Лучший ответ:

Тип list обычно выполняет фактическую инициализацию списка внутри его метода __init__(), так как это соглашение для изменяемых типов. Вам нужно только перезаписать __new__() при подтипировании неизменяемых типов. Хотя вы можете перезаписать __new__() в списке подклассов, в этом случае не так много смысла в вашем случае использования. Легче просто перезаписать __init__():

class MyList(list): def __init__(self, *args): list.__init__(self, *args) self.append(‘FirstMen’) self.name = ‘Westeros’

Также обратите внимание, что я рекомендую не использовать super() в этом случае. Вы хотите называть list.__init__() здесь, а не что-то еще.

Ответ №1

Прежде всего, делаете ли вы это упражнение для понимания __new__? Если нет, есть почти наверняка лучший способ сделать то, что вы пытаетесь сделать. Не могли бы вы объяснить, что вы хотели бы сделать здесь?

Итак, вот что происходит в вашем примере:

  • Вы вызываете MyList([1,2,3,4])
  • Это сначала вызывает MyList.__new__(MyList,[1,2,3,4])
  • Ваша реализация вызывает list.__new__(MyList,[1,2,3,4])
    Это возвращает новый экземпляр MyList без элементов. list.__new__ не заполняет список. Он оставляет это list.__init__, который никогда не вызывается.
  • Ваш метод __new__ добавляет ‘FirstMen’ в пустой экземпляр MyList.
  • Ваш метод __new__ возвращает экземпляр MyList.
    Вызывается
  • MyList.__init__([1,2,3,4]).
  • Он устанавливает атрибут name в ‘Westeros’.
  • Он возвращает.
  • Экземпляр присваивается my_list и печатается.

См. здесь объяснение __new__: http://docs.python.org/reference/datamodel.html#basic-customization

Оцените статью
Добавить комментарий