Как подклассифицировать список Python без проблем типа?
Я хочу реализовать собственный класс списка в Python в качестве подкласса list
. Каков минимальный набор методов, которые мне нужно переопределить из базового класса list
, чтобы получить полную совместимость типов для всех операций с списками?
Этот вопрос предполагает, что по крайней мере __getslice__
необходимо переопределить. Из дальнейших исследований потребуется также __add__
и __mul__
. Поэтому у меня есть этот код:
class CustomList(list):
def __getslice__(self,i,j):
return CustomList(list.__getslice__(self, i, j))
def __add__(self,other):
return CustomList(list.__add__(self,other))
def __mul__(self,other):
return CustomList(list.__mul__(self,other))
Следующие инструкции работают по желанию, даже без переопределяющих методов:
l = CustomList((1,2,3))
l.append(4)
l[0] = -1
l[0:2] = CustomList((10,11)) # type(l) is CustomList
Эти инструкции работают только с переопределяющими методами в определении класса:
l3 = l + CustomList((4,5,6)) # type(l3) is CustomList
l4 = 3*l # type(l4) is CustomList
l5 = l[0:2] # type(l5) is CustomList
Единственное, что я не знаю, как добиться, - это сделать расширенную нарезку верным правилом:
l6 = l[0:2:2] # type(l6) is list
Что мне нужно добавить в определение класса, чтобы получить CustomList
как тип l6
?
Кроме того, существуют ли другие операции над списками, отличные от расширенного среза, где результат будет иметь тип list
вместо CustomList
?
Ответы
Ответ 1
Во-первых, я рекомендую вам следовать советам Björn Pollex (+1).
Чтобы преодолеть эту конкретную проблему (type(l2 + l3) == CustomList
), вам необходимо реализовать пользовательский __add__()
:
def __add__(self, rhs):
return CustomList(list.__add__(self, rhs))
И для расширенная резка:
def __getitem__(self, item):
result = list.__getitem__(self, item)
try:
return CustomList(result)
except TypeError:
return result
Я также рекомендую...
pydoc list
... в командной строке. Вы увидите, какие методы list
выдает, и это даст вам хорошее представление о том, какие из них вам нужно переопределить.
Ответ 2
Вероятно, вы должны прочитать эти два раздела из документации:
Изменить:. Чтобы обрабатывать расширенную нарезку, вы должны сделать свой объект-срез __getitem__
-метод (см. здесь, немного ниже).