Python: реализация нарезки в __getiteM__
-
05-10-2019 - |
Вопрос
Я пытаюсь осуществить функциональность среза для класса, который я создаю, это создает векторное представление.
У меня есть этот код до сих пор, который, по которому я верю, будет правильно реализовать кусок, но всякий раз, когда я звоню как v[4]
где V векторный Python возвращает ошибку, не имею достаточно параметров. Поэтому я пытаюсь выяснить, как определить getitem
Специальный метод в моем классе для обработки как простых индексов и нарезки.
def __getitem__(self, start, stop, step):
index = start
if stop == None:
end = start + 1
else:
end = stop
if step == None:
stride = 1
else:
stride = step
return self.__data[index:end:stride]
Решение
То __getitem__()
метод получит slice
объект, когда объект нарезан. Просто посмотри на start
, stop
, а также step
члены slice
объект для того, чтобы получить компоненты для ломтика.
>>> class C(object):
... def __getitem__(self, val):
... print val
...
>>> c = C()
>>> c[3]
3
>>> c[3:4]
slice(3, 4, None)
>>> c[3:4:-2]
slice(3, 4, -2)
>>> c[():1j:'a']
slice((), 1j, 'a')
Другие советы
У меня есть «синтетический» список (тот, где данные больше, чем вы хотели бы создавать в памяти), и мой __getitem__
Похоже:
def __getitem__( self, key ) :
if isinstance( key, slice ) :
#Get the start, stop, and step from the slice
return [self[ii] for ii in xrange(*key.indices(len(self)))]
elif isinstance( key, int ) :
if key < 0 : #Handle negative indices
key += len( self )
if key < 0 or key >= len( self ) :
raise IndexError, "The index (%d) is out of range."%key
return self.getData(key) #Get the data from elsewhere
else:
raise TypeError, "Invalid argument type."
Кусок не возвращает один и тот же тип, что нет-нет, но это работает для меня.
Как определить класс GetITem, чтобы обрабатывать как простой индексы и нарезки?
Объекты среза автоматически создаются автоматически при использовании толстой кишки в обозначении подписания - и это это то, что передается __getitem__
. Отказ Использовать isinstance
Чтобы проверить, есть ли у вас объект среза:
from __future__ import print_function
class Sliceable(object):
def __getitem__(self, given):
if isinstance(given, slice):
# do your handling for a slice object:
print(given.start, given.stop, given.step)
else:
# Do your handling for a plain index
print(given)
Пример использования:
>>> sliceme = Sliceable()
>>> sliceme[1]
1
>>> sliceme[2]
2
>>> sliceme[:]
None None None
>>> sliceme[1:]
1 None None
>>> sliceme[1:2]
1 2 None
>>> sliceme[1:2:3]
1 2 3
>>> sliceme[:2:3]
None 2 3
>>> sliceme[::3]
None None 3
>>> sliceme[::]
None None None
>>> sliceme[:]
None None None
Python 2, осознавать:
В Python 2 есть устаревший метод, который вам может потребоваться переопределить при подклассах некоторых встроенных типов.
object.__getslice__(self, i, j)
Устарели с версии 2.0: Поддержка объектов срезов в качестве параметров к
__getitem__()
метод. (Тем не менее, встроенные типы в CPYthon в настоящее время все еще реализуют__getslice__()
. Отказ Поэтому вы должны переопределить его в производных классах при реализации нарезки.)
Это ушло в Python 3.
Правильный способ сделать это, чтобы иметь __getitem__
Возьмите один параметр, который может быть либо числом, либо объект среза.
Видеть:
http://docs.ython.org/library/functions.html#slice.html#slice.
http://docs.cython.org/reference/datamodel.html#object.__getitem__
Продлить ответ Аарона, для таких вещей, как numpy
, вы можете делать многомерные нарезки, проверяя, если given
это tuple
:
class Sliceable(object):
def __getitem__(self, given):
if isinstance(given, slice):
# do your handling for a slice object:
print("slice", given.start, given.stop, given.step)
elif isinstance(given, tuple):
print("multidim", given)
else:
# Do your handling for a plain index
print("plain", given)
sliceme = Sliceable()
sliceme[1]
sliceme[::]
sliceme[1:, ::2]
```
Выход:
('plain', 1)
('slice', None, None, None)
('multidim', (slice(1, None, None), slice(None, None, 2)))