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
содержит только элемент 'FirstMen'
. Почему мой __new__
здесь не работает? И как мне наследовать от встроенного типа типа list
? То же самое для неизменяемых типов, таких как str
?
Ответы
Ответ 1
Тип 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__()
здесь, а не что-то еще.
Ответ 2
Прежде всего, делаете ли вы это упражнение для понимания __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