Python: Как я могу наследовать от встроенного типа списка? - PullRequest
16 голосов
/ 24 февраля 2012

Я хочу добавить некоторые атрибуты во встроенный тип 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?

Ответы [ 2 ]

23 голосов
/ 24 февраля 2012

Тип 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__() здесь, и, возможно, больше ничего.

8 голосов
/ 24 февраля 2012

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

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

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

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

...