Ответы:
Это довольно просто на самом деле:
a[start:stop] # items start through stop-1
a[start:] # items start through the rest of the array
a[:stop] # items from the beginning through stop-1
a[:] # a copy of the whole array
Также есть step
значение, которое можно использовать с любым из вышеперечисленных:
a[start:stop:step] # start through not past stop, by step
Ключевой момент, который следует запомнить, - это то, что :stop
значение представляет собой первое значение, которого нет в выбранном срезе. Таким образом, разница между stop
и start
является количеством выбранных элементов (если step
1, по умолчанию).
Другая особенность заключается в том, что start
или stop
может быть отрицательным числом, что означает, что оно отсчитывается от конца массива, а не от начала. Так:
a[-1] # last item in the array
a[-2:] # last two items in the array
a[:-2] # everything except the last two items
Аналогично step
может быть отрицательное число:
a[::-1] # all items in the array, reversed
a[1::-1] # the first two items, reversed
a[:-3:-1] # the last two items, reversed
a[-3::-1] # everything except the last two items, reversed
Python добр к программисту, если в нем меньше элементов, чем вы просите. Например, если вы запрашиваете a[:-2]
и a
содержит только один элемент, вместо ошибки вы получите пустой список. Иногда вы бы предпочли ошибку, поэтому вы должны знать, что это может произойти.
slice()
объектуОператор среза []
фактически используется в приведенном выше коде с slice()
объектом с использованием :
нотации (которая действительна только внутри []
), то есть:
a[start:stop:step]
эквивалентно:
a[slice(start, stop, step)]
Объекты среза также ведут себя немного по-разному в зависимости от количества аргументов, аналогично range()
, то есть оба slice(stop)
и slice(start, stop[, step])
поддерживаются. Чтобы пропустить указание заданного аргумента, можно использовать None
, например a[start:]
, эквивалентно a[slice(start, None)]
или a[::-1]
эквивалентно a[slice(None, None, -1)]
.
Хотя :
нотация на основе очень полезна для простого среза, явное использование slice()
объектов упрощает программную генерацию среза.
None
любое из пустых мест. Например [None:None]
делает целую копию. Это полезно, когда вам нужно указать конец диапазона, используя переменную, и вам нужно включить последний элемент.
del
делает запись нотации. В частности, del arr[:]
не сразу очевидно («arr [:] делает копию, поэтому удаляет эту копию ???» и т. Д.)
Об этом рассказывается в руководстве по Python (прокрутите немного вниз, пока не дойдете до части о нарезке).
Рисунок ASCII также полезен для запоминания работы срезов:
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5 6
-6 -5 -4 -3 -2 -1
Один из способов помнить, как работают срезы, - рассматривать индексы как указывающие между символами, причем левый край первого символа пронумерован 0. Тогда правый край последнего символа строки из n символов имеет индекс n .
a[-4,-6,-1]
чтобы быть , yP
но это ty
. То, что всегда работает, - это думать в символах или слотах и использовать индексирование как полуоткрытый интервал - справа, если положительный шаг, или слева, если отрицательный шаг.
x[:0]
происходит при запуске с начала), поэтому вам придется использовать специальные массивы для небольших случаев. : /
Перечисляя возможности, допускаемые грамматикой:
>>> seq[:] # [seq[0], seq[1], ..., seq[-1] ]
>>> seq[low:] # [seq[low], seq[low+1], ..., seq[-1] ]
>>> seq[:high] # [seq[0], seq[1], ..., seq[high-1]]
>>> seq[low:high] # [seq[low], seq[low+1], ..., seq[high-1]]
>>> seq[::stride] # [seq[0], seq[stride], ..., seq[-1] ]
>>> seq[low::stride] # [seq[low], seq[low+stride], ..., seq[-1] ]
>>> seq[:high:stride] # [seq[0], seq[stride], ..., seq[high-1]]
>>> seq[low:high:stride] # [seq[low], seq[low+stride], ..., seq[high-1]]
Конечно, если (high-low)%stride != 0
, тогда конечная точка будет немного ниже, чем high-1
.
Если stride
отрицательный, порядок немного меняется, так как мы ведем обратный отсчет:
>>> seq[::-stride] # [seq[-1], seq[-1-stride], ..., seq[0] ]
>>> seq[high::-stride] # [seq[high], seq[high-stride], ..., seq[0] ]
>>> seq[:low:-stride] # [seq[-1], seq[-1-stride], ..., seq[low+1]]
>>> seq[high:low:-stride] # [seq[high], seq[high-stride], ..., seq[low+1]]
Расширенные срезы (с запятыми и эллипсами) в основном используются только специальными структурами данных (например, NumPy); основные последовательности не поддерживают их.
>>> class slicee:
... def __getitem__(self, item):
... return repr(item)
...
>>> slicee()[0, 1:2, ::5, ...]
'(0, slice(1, 2, None), slice(None, None, 5), Ellipsis)'
repr
__getitem__
является; ваш пример эквивалентен apple[slice(4, -4, -1)]
.
Ответы выше не обсуждают назначение срезов. Чтобы понять назначение срезов, полезно добавить еще одну концепцию в искусство ASCII:
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
Slice position: 0 1 2 3 4 5 6
Index position: 0 1 2 3 4 5
>>> p = ['P','y','t','h','o','n']
# Why the two sets of numbers:
# indexing gives items, not lists
>>> p[0]
'P'
>>> p[5]
'n'
# Slicing gives lists
>>> p[0:1]
['P']
>>> p[0:2]
['P','y']
Одна эвристика, для среза от нуля до n, подумайте: «ноль - это начало, начните с начала и возьмите n элементов в списке».
>>> p[5] # the last of six items, indexed from zero
'n'
>>> p[0:5] # does NOT include the last item!
['P','y','t','h','o']
>>> p[0:6] # not p[0:5]!!!
['P','y','t','h','o','n']
Другая эвристика: «для любого среза замените начало на ноль, примените предыдущую эвристику, чтобы получить конец списка, а затем сосчитайте первое число обратно, чтобы отрезать элементы от начала».
>>> p[0:4] # Start at the beginning and count out 4 items
['P','y','t','h']
>>> p[1:4] # Take one item off the front
['y','t','h']
>>> p[2:4] # Take two items off the front
['t','h']
# etc.
Первое правило назначения срезов заключается в том, что, поскольку срезы возвращают список, для назначения срезов требуется список (или другие итерируемые):
>>> p[2:3]
['t']
>>> p[2:3] = ['T']
>>> p
['P','y','T','h','o','n']
>>> p[2:3] = 't'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only assign an iterable
Второе правило назначения слайсов, которое вы также можете видеть выше, заключается в том, что любая часть списка, возвращаемая при индексации слайсов, это та же самая часть, которая изменяется при назначении слайсов:
>>> p[2:4]
['T','h']
>>> p[2:4] = ['t','r']
>>> p
['P','y','t','r','o','n']
Третье правило назначения слайсов состоит в том, что назначенный список (повторяемый) не должен иметь одинаковую длину; Индексированный фрагмент просто вырезается и заменяется массой на все, что ему назначено:
>>> p = ['P','y','t','h','o','n'] # Start over
>>> p[2:4] = ['s','p','a','m']
>>> p
['P','y','s','p','a','m','o','n']
Самая хитрая часть, к которой нужно привыкнуть, - это назначение пустым слайсам. Используя эвристику 1 и 2, легко разобраться с индексированием пустого фрагмента:
>>> p = ['P','y','t','h','o','n']
>>> p[0:4]
['P','y','t','h']
>>> p[1:4]
['y','t','h']
>>> p[2:4]
['t','h']
>>> p[3:4]
['h']
>>> p[4:4]
[]
И затем, как только вы это увидели, назначение слайса пустому слайсу также имеет смысл:
>>> p = ['P','y','t','h','o','n']
>>> p[2:4] = ['x','y'] # Assigned list is same length as slice
>>> p
['P','y','x','y','o','n'] # Result is same length
>>> p = ['P','y','t','h','o','n']
>>> p[3:4] = ['x','y'] # Assigned list is longer than slice
>>> p
['P','y','t','x','y','o','n'] # The result is longer
>>> p = ['P','y','t','h','o','n']
>>> p[4:4] = ['x','y']
>>> p
['P','y','t','h','x','y','o','n'] # The result is longer still
Обратите внимание, что, поскольку мы не меняем второе число среза (4), вставленные элементы всегда располагаются прямо напротив «o», даже когда мы назначаем пустой срез. Таким образом, позиция для пустого назначения среза является логическим расширением позиций для непустых назначений среза.
Немного резервного копирования, что произойдет, если вы продолжите нашу процессию подсчета начала среза?
>>> p = ['P','y','t','h','o','n']
>>> p[0:4]
['P','y','t','h']
>>> p[1:4]
['y','t','h']
>>> p[2:4]
['t','h']
>>> p[3:4]
['h']
>>> p[4:4]
[]
>>> p[5:4]
[]
>>> p[6:4]
[]
С нарезкой, как только вы закончите, вы закончите; это не начинает разрезать назад. В Python вы не получите отрицательных шагов, если вы явно не попросите их, используя отрицательное число.
>>> p[5:3:-1]
['n','o']
Есть несколько странных последствий для правила «как только вы закончите, вы закончите»:
>>> p[4:4]
[]
>>> p[5:4]
[]
>>> p[6:4]
[]
>>> p[6]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
Фактически, по сравнению с индексированием, нарезка Python причудливо защищена от ошибок:
>>> p[100:200]
[]
>>> p[int(2e99):int(1e99)]
[]
Иногда это может пригодиться, но также может привести к несколько странному поведению:
>>> p
['P', 'y', 't', 'h', 'o', 'n']
>>> p[int(2e99):int(1e99)] = ['p','o','w','e','r']
>>> p
['P', 'y', 't', 'h', 'o', 'n', 'p', 'o', 'w', 'e', 'r']
В зависимости от вашего приложения это может ... или не может ... быть тем, на что вы надеялись!
Ниже приведен текст моего оригинального ответа. Это было полезно для многих людей, поэтому я не хотел его удалять.
>>> r=[1,2,3,4]
>>> r[1:1]
[]
>>> r[1:1]=[9,8]
>>> r
[1, 9, 8, 2, 3, 4]
>>> r[1:1]=['blah']
>>> r
[1, 'blah', 9, 8, 2, 3, 4]
Это также может прояснить разницу между нарезкой и индексацией.
Объясните обозначение среза Python
Короче говоря, колоны ( :
) в индексном обозначении ( subscriptable[subscriptarg]
) делает срез обозначение - у которого есть необязательные аргументы, start
, stop
, step
:
sliceable[start:stop:step]
Python Slice - это вычислительно быстрый способ для методического доступа к частям ваших данных. На мой взгляд, чтобы быть даже программистом среднего уровня на Python, это один из аспектов языка, с которым необходимо быть знакомым.
Для начала давайте определимся с несколькими терминами:
start: начальный индекс среза, он будет включать в себя элемент с этим индексом, если он не совпадает со стопом , по умолчанию равен 0, т.е. первый индекс. Если оно отрицательное, это значит начинать
n
предметы с конца.stop: конечный индекс среза, он не включает в себя элемент с этим индексом, по умолчанию длина отрезка последовательности, то есть до конца включительно.
шаг: величина, на которую увеличивается индекс, по умолчанию равен 1. Если он отрицательный, вы разрезаете итеративное в обратном порядке.
Вы можете сделать любое из этих положительных или отрицательных чисел. Смысл положительных чисел является простым, но для отрицательных чисел, так же , как индексы в Python, считать в обратном порядке от конца для начала и остановок , а также за шагом , вы просто уменьшаете индекс. Этот пример взят из учебного пособия по документации , но я немного изменил его, чтобы указать, на какой элемент в последовательности ссылается каждый индекс:
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5
-6 -5 -4 -3 -2 -1
Чтобы использовать нотацию среза с последовательностью, которая ее поддерживает, необходимо включить хотя бы одно двоеточие в квадратные скобки, которые следуют за последовательностью (которые фактически реализуют __getitem__
метод последовательности, согласно модели данных Python ).
Запись среза работает следующим образом:
sequence[start:stop:step]
И помните, что есть настройки по умолчанию для запуска , остановки и шага , поэтому для доступа к значениям по умолчанию просто пропустите аргумент.
Запись среза, чтобы получить последние девять элементов из списка (или любой другой последовательности, которая поддерживает его, например, строку), будет выглядеть следующим образом:
my_list[-9:]
Когда я вижу это, я читаю часть в скобках как «9-е от конца до конца». (На самом деле, я мысленно сокращаю это как "-9, на")
Полная запись
my_list[-9:None:None]
и подставить значения по умолчанию ( на самом деле , когда step
отрицательный, stop
по умолчанию имеет значение -len(my_list) - 1
, поэтому None
для остановки на самом деле просто означает , что он идет в зависимости от того , конечный шаг берет его к):
my_list[-9:len(my_list):1]
Толстой кишки , :
является то , что говорит Python , что вы даете ему кусочек , а не регулярный индекс. Вот почему идиоматический способ создания мелкой копии списков в Python 2
list_copy = sequence[:]
И очистка их с:
del my_list[:]
(Python 3 получает list.copy
иlist.clear
метод.)
step
отрицательно, значения по умолчанию для start
иstop
изменитьПо умолчанию, когда step
аргумент пуст (или None
), он присваивается+1
.
Но вы можете передать отрицательное целое число, и список (или большинство других стандартных разрезаемых элементов) будет разрезан от конца до начала.
Таким образом, отрицательный срез изменит значения по умолчанию для start
и stop
!
Мне нравится поощрять пользователей читать как источник, так и документацию. Исходный код ломтика объекты и эта логика здесь . Сначала мы определяем, step
является ли оно отрицательным:
step_is_negative = step_sign < 0;
Если это так, нижняя граница -1
означает, что мы нарезаем весь путь вплоть до начала, а верхняя граница - это длина минус 1, что означает, что мы начинаем с конца. (Обратите внимание , что семантика этого -1
является отличается от А , -1
что пользователи могут переходить индексы в Python , указывающие на последний элемент.)
if (step_is_negative) { lower = PyLong_FromLong(-1L); if (lower == NULL) goto error; upper = PyNumber_Add(length, lower); if (upper == NULL) goto error; }
В противном случае step
положительно, и нижняя граница будет равна нулю, а верхняя граница (до которой мы идем, но не включая) длины нарезанного списка.
else { lower = _PyLong_Zero; Py_INCREF(lower); upper = length; Py_INCREF(upper); }
Затем нам может потребоваться применить значения по умолчанию для start
и stop
- значение по умолчанию для for start
рассчитывается как верхняя граница, когда step
она отрицательна:
if (self->start == Py_None) { start = step_is_negative ? upper : lower; Py_INCREF(start); }
и stop
нижняя граница:
if (self->stop == Py_None) { stop = step_is_negative ? lower : upper; Py_INCREF(stop); }
Может оказаться полезным отделить формирование среза от передачи его list.__getitem__
методу (это то, что делают квадратные скобки ). Даже если вы не новичок в этом, он делает ваш код более читабельным, чтобы другие, которым, возможно, придется читать ваш код, могли более легко понять, что вы делаете.
Однако вы не можете просто присвоить переменной целые числа, разделенные двоеточиями. Вам нужно использовать объект среза:
last_nine_slice = slice(-9, None)
Второй аргумент, None
обязателен, так что первый аргумент интерпретируется как start
аргумент, иначе это будет stop
аргумент .
Затем вы можете передать объект слайса в вашу последовательность:
>>> list(range(100))[last_nine_slice]
[91, 92, 93, 94, 95, 96, 97, 98, 99]
Интересно, что диапазоны также берут кусочки:
>>> range(100)[last_nine_slice]
range(91, 100)
Так как фрагменты списков Python создают новые объекты в памяти, следует помнить о другой важной функции itertools.islice
. Обычно вам нужно перебирать фрагмент, а не просто создавать его статически в памяти. islice
идеально подходит для этого. Протест, он не поддерживает отрицательные аргументы start
, stop
или step
, так что если это вопрос , вам могут понадобиться для расчета индексов или реверсом итерации заранее.
length = 100
last_nine_iter = itertools.islice(list(range(length)), length-9, None, 1)
list_last_nine = list(last_nine_iter)
и сейчас:
>>> list_last_nine
[91, 92, 93, 94, 95, 96, 97, 98, 99]
Тот факт, что срезы списков делают копию, является особенностью самих списков. Если вы нарезаете сложные объекты, такие как Pandas DataFrame, он может вернуть представление оригинала, а не его копию.
И пара вещей, которые не были сразу очевидны для меня, когда я впервые увидел синтаксис среза:
>>> x = [1,2,3,4,5,6]
>>> x[::-1]
[6,5,4,3,2,1]
Простой способ изменить последовательность!
И если вы хотите, по какой-то причине, каждый второй элемент в обратной последовательности:
>>> x = [1,2,3,4,5,6]
>>> x[::-2]
[6,4,2]
В Python 2.7
Нарезка в Python
[a:b:c]
len = length of string, tuple or list
c -- default is +1. The sign of c indicates forward or backward, absolute value of c indicates steps. Default is forward with step size 1. Positive means forward, negative means backward.
a -- When c is positive or blank, default is 0. When c is negative, default is -1.
b -- When c is positive or blank, default is len. When c is negative, default is -(len+1).
Понимание назначения индекса очень важно.
In forward direction, starts at 0 and ends at len-1
In backward direction, starts at -1 and ends at -len
Когда вы говорите [a: b: c], вы говорите, в зависимости от знака c (вперед или назад), начинайте с a и заканчивайте на b (исключая элемент с индексом b). Используйте вышеприведенное правило индексации и помните, что вы найдете только элементы в этом диапазоне:
-len, -len+1, -len+2, ..., 0, 1, 2,3,4 , len -1
Но этот диапазон продолжается в обоих направлениях бесконечно:
...,-len -2 ,-len-1,-len, -len+1, -len+2, ..., 0, 1, 2,3,4 , len -1, len, len +1, len+2 , ....
Например:
0 1 2 3 4 5 6 7 8 9 10 11
a s t r i n g
-9 -8 -7 -6 -5 -4 -3 -2 -1
Если ваш выбор a, b и c позволяет перекрываться с указанным выше диапазоном, когда вы проходите, используя правила для a, b, c выше, вы либо получите список с элементами (затронутый во время обхода), либо вы получите пустой список.
И последнее: если a и b равны, вы также получаете пустой список:
>>> l1
[2, 3, 4]
>>> l1[:]
[2, 3, 4]
>>> l1[::-1] # a default is -1 , b default is -(len+1)
[4, 3, 2]
>>> l1[:-4:-1] # a default is -1
[4, 3, 2]
>>> l1[:-3:-1] # a default is -1
[4, 3]
>>> l1[::] # c default is +1, so a default is 0, b default is len
[2, 3, 4]
>>> l1[::-1] # c is -1 , so a default is -1 and b default is -(len+1)
[4, 3, 2]
>>> l1[-100:-200:-1] # Interesting
[]
>>> l1[-1:-200:-1] # Interesting
[4, 3, 2]
>>> l1[-1:-1:1]
[]
>>> l1[-1:5:1] # Interesting
[4]
>>> l1[1:-7:1]
[]
>>> l1[1:-7:-1] # Interesting
[3, 2]
>>> l1[:-2:-2] # a default is -1, stop(b) at -2 , step(c) by 2 in reverse direction
[4]
a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]; a[:-2:-2]
который приводит к[9]
Нашел эту великолепную таблицу по адресу http://wiki.python.org/moin/MovingToPythonFromOtherLanguages
Python indexes and slices for a six-element list.
Indexes enumerate the elements, slices enumerate the spaces between the elements.
Index from rear: -6 -5 -4 -3 -2 -1 a=[0,1,2,3,4,5] a[1:]==[1,2,3,4,5]
Index from front: 0 1 2 3 4 5 len(a)==6 a[:5]==[0,1,2,3,4]
+---+---+---+---+---+---+ a[0]==0 a[:-2]==[0,1,2,3]
| a | b | c | d | e | f | a[5]==5 a[1:2]==[1]
+---+---+---+---+---+---+ a[-1]==5 a[1:-1]==[1,2,3,4]
Slice from front: : 1 2 3 4 5 : a[-2]==4
Slice from rear: : -5 -4 -3 -2 -1 :
b=a[:]
b==[0,1,2,3,4,5] (shallow copy of a)
После небольшого использования я понимаю, что самое простое описание - это то же самое, что и аргументы в for
цикле ...
(from:to:step)
Любые из них являются необязательными:
(:to:step)
(from::step)
(from:to)
Тогда для отрицательного индексирования нужно, чтобы вы добавили длину строки к отрицательным индексам, чтобы понять это.
В любом случае это работает для меня ...
Мне легче вспомнить, как это работает, и затем я могу определить любую конкретную комбинацию старт / стоп / шаг.
Поучительно range()
сначала понять :
def range(start=0, stop, step=1): # Illegal syntax, but that's the effect
i = start
while (i < stop if step > 0 else i > stop):
yield i
i += step
Начните с start
, увеличивайте step
, не достигайте stop
. Очень просто.
О негативном шаге следует помнить, что stop
это всегда исключаемый конец, будь то выше или ниже. Если вы хотите, чтобы один и тот же срез находился в обратном порядке, гораздо проще сделать инверсию по отдельности: например, 'abcde'[1:-2][::-1]
срезать один символ слева, два справа, а затем поменять местами. (Смотри также reversed()
.)
Секвенция секвенции такая же, за исключением того, что сначала она нормализует отрицательные индексы и никогда не может выходить за пределы последовательности:
TODO : В приведенном ниже коде была ошибка «никогда не выходить за пределы последовательности», когда abs (step)> 1; Я думаю, что я исправил это, чтобы быть правильным, но это трудно понять.
def this_is_how_slicing_works(seq, start=None, stop=None, step=1):
if start is None:
start = (0 if step > 0 else len(seq)-1)
elif start < 0:
start += len(seq)
if not 0 <= start < len(seq): # clip if still outside bounds
start = (0 if step > 0 else len(seq)-1)
if stop is None:
stop = (len(seq) if step > 0 else -1) # really -1, not last element
elif stop < 0:
stop += len(seq)
for i in range(start, stop, step):
if 0 <= i < len(seq):
yield seq[i]
Не беспокойтесь о is None
деталях - просто помните, что опускание start
и / или stop
всегда делает правильные вещи, чтобы дать вам всю последовательность.
Нормализация отрицательных индексов сначала позволяет независимо начинать и / или останавливать отсчет с конца: 'abcde'[1:-2] == 'abcde'[1:3] == 'bc'
несмотря на range(1,-2) == []
. Нормализация иногда рассматривается как «по модулю длины», но обратите внимание, что она добавляет длину только один раз: например, 'abcde'[-53:42]
это просто целая строка.
this_is_how_slicing_works
не то же самое, что срез питона. EG [0, 1, 2][-5:3:3]
получит [0] в python, но list(this_is_how_slicing_works([0, 1, 2], -5, 3, 3))
получит [1].
range(4)[-200:200:3] == [0, 3]
но list(this_is_how_slicing_works([0, 1, 2, 3], -200, 200, 3)) == [2]
. Моя if 0 <= i < len(seq):
попытка реализовать «никогда не выходить за пределы последовательности» просто, но не подходит для шага> 1. Я перепишу это позже сегодня (с тестами).
Index:
------------>
0 1 2 3 4
+---+---+---+---+---+
| a | b | c | d | e |
+---+---+---+---+---+
0 -4 -3 -2 -1
<------------
Slice:
<---------------|
|--------------->
: 1 2 3 4 :
+---+---+---+---+---+
| a | b | c | d | e |
+---+---+---+---+---+
: -4 -3 -2 -1 :
|--------------->
<---------------|
Я надеюсь, что это поможет вам смоделировать список в Python.
Ссылка: http://wiki.python.org/moin/MovingToPythonFromOtherLanguages
Обозначение среза Python:
a[start:end:step]
start
и end
, отрицательные значения интерпретируются как относящиеся к концу последовательности.end
обозначения позиции после последнего включаемого элемента.[+0:-0:1]
.start
иend
Обозначения распространяются на (NumPy) матриц и многомерных массивов. Например, чтобы разрезать целые столбцы, вы можете использовать:
m[::,0:2:] ## slice the first two columns
Срезы содержат ссылки, а не копии элементов массива. Если вы хотите сделать отдельную копию массива, вы можете использовать deepcopy()
.
Это просто для дополнительной информации ... Рассмотрим список ниже
>>> l=[12,23,345,456,67,7,945,467]
Несколько других приемов для изменения списка:
>>> l[len(l):-len(l)-1:-1]
[467, 945, 7, 67, 456, 345, 23, 12]
>>> l[:-len(l)-1:-1]
[467, 945, 7, 67, 456, 345, 23, 12]
>>> l[len(l)::-1]
[467, 945, 7, 67, 456, 345, 23, 12]
>>> l[::-1]
[467, 945, 7, 67, 456, 345, 23, 12]
>>> l[-1:-len(l)-1:-1]
[467, 945, 7, 67, 456, 345, 23, 12]
Вот как я преподаю ломтики новичкам:
Понимание разницы между индексированием и нарезкой:
У Wiki Python есть эта удивительная картина, которая четко различает индексацию и нарезку.
Это список из шести элементов. Чтобы лучше понять нарезку, рассмотрите этот список как набор из шести блоков, помещенных вместе. В каждой коробке есть алфавит.
Индексирование похоже на работу с содержимым коробки. Вы можете проверить содержимое любой коробки. Но вы не можете проверить содержимое нескольких ящиков одновременно. Вы даже можете заменить содержимое коробки. Но вы не можете поместить два шара в одну коробку или заменить два шара одновременно.
In [122]: alpha = ['a', 'b', 'c', 'd', 'e', 'f']
In [123]: alpha
Out[123]: ['a', 'b', 'c', 'd', 'e', 'f']
In [124]: alpha[0]
Out[124]: 'a'
In [127]: alpha[0] = 'A'
In [128]: alpha
Out[128]: ['A', 'b', 'c', 'd', 'e', 'f']
In [129]: alpha[0,1]
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-129-c7eb16585371> in <module>()
----> 1 alpha[0,1]
TypeError: list indices must be integers, not tuple
Нарезка подобна работе с самими коробками. Вы можете взять первую коробку и поставить ее на другой стол. Чтобы поднять коробку, все, что вам нужно знать, это положение начала и конца коробки.
Вы можете даже выбрать первые три блока или последние два блока или все блоки от 1 до 4. Таким образом, вы можете выбрать любой набор блоков, если вы знаете начало и конец. Эти позиции называются начальной и конечной позициями.
Интересно то, что вы можете заменить несколько коробок одновременно. Также вы можете разместить несколько ящиков где угодно.
In [130]: alpha[0:1]
Out[130]: ['A']
In [131]: alpha[0:1] = 'a'
In [132]: alpha
Out[132]: ['a', 'b', 'c', 'd', 'e', 'f']
In [133]: alpha[0:2] = ['A', 'B']
In [134]: alpha
Out[134]: ['A', 'B', 'c', 'd', 'e', 'f']
In [135]: alpha[2:2] = ['x', 'xx']
In [136]: alpha
Out[136]: ['A', 'B', 'x', 'xx', 'c', 'd', 'e', 'f']
Нарезка с шагом:
До сих пор вы постоянно выбирали коробки. Но иногда нужно подобрать дискретно. Например, вы можете подобрать каждую вторую коробку. Вы можете даже забрать каждую третью коробку с конца. Это значение называется размером шага. Это представляет разрыв между вашими последующими пикапами. Размер шага должен быть положительным, если вы выбираете поля от начала до конца и наоборот.
In [137]: alpha = ['a', 'b', 'c', 'd', 'e', 'f']
In [142]: alpha[1:5:2]
Out[142]: ['b', 'd']
In [143]: alpha[-1:-5:-2]
Out[143]: ['f', 'd']
In [144]: alpha[1:5:-2]
Out[144]: []
In [145]: alpha[-1:-5:2]
Out[145]: []
Как Python вычисляет недостающие параметры:
При нарезке, если вы пропустите какой-либо параметр, Python пытается выяснить это автоматически.
Если вы проверите исходный код CPython , вы найдете функцию PySlice_GetIndicesEx (), которая вычисляет индексы для среза для любых заданных параметров. Вот логический эквивалент кода в Python.
Эта функция принимает объект Python и необязательные параметры для нарезки и возвращает начало, конец, шаг и длину среза для запрошенного среза.
def py_slice_get_indices_ex(obj, start=None, stop=None, step=None):
length = len(obj)
if step is None:
step = 1
if step == 0:
raise Exception("Step cannot be zero.")
if start is None:
start = 0 if step > 0 else length - 1
else:
if start < 0:
start += length
if start < 0:
start = 0 if step > 0 else -1
if start >= length:
start = length if step > 0 else length - 1
if stop is None:
stop = length if step > 0 else -1
else:
if stop < 0:
stop += length
if stop < 0:
stop = 0 if step > 0 else -1
if stop >= length:
stop = length if step > 0 else length - 1
if (step < 0 and stop >= start) or (step > 0 and start >= stop):
slice_length = 0
elif step < 0:
slice_length = (stop - start + 1)/(step) + 1
else:
slice_length = (stop - start - 1)/(step) + 1
return (start, stop, step, slice_length)
Это интеллект, который присутствует за кусочками. Поскольку в Python есть встроенная функция, называемая slice, вы можете передать некоторые параметры и проверить, насколько разумно он рассчитывает отсутствующие параметры.
In [21]: alpha = ['a', 'b', 'c', 'd', 'e', 'f']
In [22]: s = slice(None, None, None)
In [23]: s
Out[23]: slice(None, None, None)
In [24]: s.indices(len(alpha))
Out[24]: (0, 6, 1)
In [25]: range(*s.indices(len(alpha)))
Out[25]: [0, 1, 2, 3, 4, 5]
In [26]: s = slice(None, None, -1)
In [27]: range(*s.indices(len(alpha)))
Out[27]: [5, 4, 3, 2, 1, 0]
In [28]: s = slice(None, 3, -1)
In [29]: range(*s.indices(len(alpha)))
Out[29]: [5, 4]
Примечание. Этот пост изначально был написан в моем блоге «Интеллект за кусочками Python» .
Как правило, написание кода с большим количеством жестко закодированных значений индекса приводит к беспорядку читаемости и обслуживания. Например, если вы вернетесь к коду год спустя, вы посмотрите на него и удивитесь, о чем вы думали, когда писали его. Показанное решение - просто способ более четко определить, что на самом деле делает ваш код. Как правило, встроенный slice () создает объект слайса, который можно использовать везде, где разрешен слайс. Например:
>>> items = [0, 1, 2, 3, 4, 5, 6]
>>> a = slice(2, 4)
>>> items[2:4]
[2, 3]
>>> items[a]
[2, 3]
>>> items[a] = [10,11]
>>> items
[0, 1, 10, 11, 4, 5, 6]
>>> del items[a]
>>> items
[0, 1, 4, 5, 6]
Если у вас есть экземпляр слайса s, вы можете получить больше информации о нем, посмотрев на его атрибуты s.start, s.stop и s.step соответственно. Например:
>>> a = slice(10, 50, 2) >>> a.start 10 >>> a.stop 50 >>> a.step 2 >>>
Чтобы было проще, помните, что ломтик имеет только одну форму:
s[start:end:step]
и вот как это работает:
s
: объект, который можно нарезатьstart
: первый индекс для начала итерацииend
: последний индекс, ОБРАТИТЕ ВНИМАНИЕ, что end
индекс не будет включен в результирующий фрагментstep
: выбрать элемент каждого step
индексаДругой импорт вещь: все start
, end
, step
может быть опущена! И если они опущены, будет использовано их значение по умолчанию: 0
, len(s)
,1
соответственно.
Итак, возможные варианты:
# Mostly used variations
s[start:end]
s[start:]
s[:end]
# Step-related variations
s[:end:step]
s[start::step]
s[::step]
# Make a copy
s[:]
ПРИМЕЧАНИЕ. Если start >= end
(учитывая только когда step>0
), Python вернет пустой фрагмент[]
.
Вышеприведенная часть объясняет основные особенности того, как работает слайс, и он будет работать в большинстве случаев. Однако могут быть подводные камни, на которые следует обратить внимание, и эта часть объясняет их.
Самое первое, что смущает изучающих Python, это то, что индекс может быть отрицательным! Не паникуйте: отрицательный индекс означает обратный отсчет.
Например:
s[-5:] # Start at the 5th index from the end of array,
# thus returning the last 5 elements.
s[:-5] # Start at index 0, and end until the 5th index from end of array,
# thus returning s[0:len(s)-5].
Делать вещи более запутанными - это step
тоже может быть негативно!
Отрицательный шаг означает итерацию массива в обратном направлении: от конца к началу, с включенным индексом конца и индексом начала, исключенным из результата.
Примечание : если шаг отрицательный, значение по умолчанию start
является len(s)
(пока end
не составит 0
, так как s[::-1]
содержит s[0]
). Например:
s[::-1] # Reversed slice
s[len(s)::-1] # The same as above, reversed slice
s[0:len(s):-1] # Empty list
Будьте удивлены: слайс не вызывает ошибку IndexError, когда индекс выходит за пределы диапазона!
Если индекс находится вне диапазона, Python будет пытаться все возможное , чтобы установить индекс 0
или в len(s)
зависимости от ситуации. Например:
s[:len(s)+5] # The same as s[:len(s)]
s[-len(s)-5::] # The same as s[0:]
s[len(s)+5::-1] # The same as s[len(s)::-1], and the same as s[::-1]
Давайте закончим этот ответ примерами, объясняя все, что мы обсуждали:
# Create our array for demonstration
In [1]: s = [i for i in range(10)]
In [2]: s
Out[2]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [3]: s[2:] # From index 2 to last index
Out[3]: [2, 3, 4, 5, 6, 7, 8, 9]
In [4]: s[:8] # From index 0 up to index 8
Out[4]: [0, 1, 2, 3, 4, 5, 6, 7]
In [5]: s[4:7] # From index 4 (included) up to index 7(excluded)
Out[5]: [4, 5, 6]
In [6]: s[:-2] # Up to second last index (negative index)
Out[6]: [0, 1, 2, 3, 4, 5, 6, 7]
In [7]: s[-2:] # From second last index (negative index)
Out[7]: [8, 9]
In [8]: s[::-1] # From last to first in reverse order (negative step)
Out[8]: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
In [9]: s[::-2] # All odd numbers in reversed order
Out[9]: [9, 7, 5, 3, 1]
In [11]: s[-2::-2] # All even numbers in reversed order
Out[11]: [8, 6, 4, 2, 0]
In [12]: s[3:15] # End is out of range, and Python will set it to len(s).
Out[12]: [3, 4, 5, 6, 7, 8, 9]
In [14]: s[5:1] # Start > end; return empty list
Out[14]: []
In [15]: s[11] # Access index 11 (greater than len(s)) will raise an IndexError
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-15-79ffc22473a3> in <module>()
----> 1 s[11]
IndexError: list index out of range
В предыдущих ответах не обсуждается разделение многомерных массивов, что возможно при использовании известного пакета NumPy :
Нарезка также может быть применена к многомерным массивам.
# Here, a is a NumPy array
>>> a
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
>>> a[:2, 0:3:2]
array([[1, 3],
[5, 7]])
« :2
» Перед запятой действует в первом измерении, а « 0:3:2
» после запятой действует во втором измерении.
list
но только на array
Numpy
#!/usr/bin/env python
def slicegraphical(s, lista):
if len(s) > 9:
print """Enter a string of maximum 9 characters,
so the printig would looki nice"""
return 0;
# print " ",
print ' '+'+---' * len(s) +'+'
print ' ',
for letter in s:
print '| {}'.format(letter),
print '|'
print " ",; print '+---' * len(s) +'+'
print " ",
for letter in range(len(s) +1):
print '{} '.format(letter),
print ""
for letter in range(-1*(len(s)), 0):
print ' {}'.format(letter),
print ''
print ''
for triada in lista:
if len(triada) == 3:
if triada[0]==None and triada[1] == None and triada[2] == None:
# 000
print s+'[ : : ]' +' = ', s[triada[0]:triada[1]:triada[2]]
elif triada[0] == None and triada[1] == None and triada[2] != None:
# 001
print s+'[ : :{0:2d} ]'.format(triada[2], '','') +' = ', s[triada[0]:triada[1]:triada[2]]
elif triada[0] == None and triada[1] != None and triada[2] == None:
# 010
print s+'[ :{0:2d} : ]'.format(triada[1]) +' = ', s[triada[0]:triada[1]:triada[2]]
elif triada[0] == None and triada[1] != None and triada[2] != None:
# 011
print s+'[ :{0:2d} :{1:2d} ]'.format(triada[1], triada[2]) +' = ', s[triada[0]:triada[1]:triada[2]]
elif triada[0] != None and triada[1] == None and triada[2] == None:
# 100
print s+'[{0:2d} : : ]'.format(triada[0]) +' = ', s[triada[0]:triada[1]:triada[2]]
elif triada[0] != None and triada[1] == None and triada[2] != None:
# 101
print s+'[{0:2d} : :{1:2d} ]'.format(triada[0], triada[2]) +' = ', s[triada[0]:triada[1]:triada[2]]
elif triada[0] != None and triada[1] != None and triada[2] == None:
# 110
print s+'[{0:2d} :{1:2d} : ]'.format(triada[0], triada[1]) +' = ', s[triada[0]:triada[1]:triada[2]]
elif triada[0] != None and triada[1] != None and triada[2] != None:
# 111
print s+'[{0:2d} :{1:2d} :{2:2d} ]'.format(triada[0], triada[1], triada[2]) +' = ', s[triada[0]:triada[1]:triada[2]]
elif len(triada) == 2:
if triada[0] == None and triada[1] == None:
# 00
print s+'[ : ] ' + ' = ', s[triada[0]:triada[1]]
elif triada[0] == None and triada[1] != None:
# 01
print s+'[ :{0:2d} ] '.format(triada[1]) + ' = ', s[triada[0]:triada[1]]
elif triada[0] != None and triada[1] == None:
# 10
print s+'[{0:2d} : ] '.format(triada[0]) + ' = ', s[triada[0]:triada[1]]
elif triada[0] != None and triada[1] != None:
# 11
print s+'[{0:2d} :{1:2d} ] '.format(triada[0],triada[1]) + ' = ', s[triada[0]:triada[1]]
elif len(triada) == 1:
print s+'[{0:2d} ] '.format(triada[0]) + ' = ', s[triada[0]]
if __name__ == '__main__':
# Change "s" to what ever string you like, make it 9 characters for
# better representation.
s = 'COMPUTERS'
# add to this list different lists to experement with indexes
# to represent ex. s[::], use s[None, None,None], otherwise you get an error
# for s[2:] use s[2:None]
lista = [[4,7],[2,5,2],[-5,1,-1],[4],[-4,-6,-1], [2,-3,1],[2,-3,-1], [None,None,-1],[-5,None],[-5,0,-1],[-5,None,-1],[-1,1,-2]]
slicegraphical(s, lista)
Вы можете запустить этот скрипт и поэкспериментировать с ним, ниже приведены некоторые примеры, которые я получил из скрипта.
+---+---+---+---+---+---+---+---+---+
| C | O | M | P | U | T | E | R | S |
+---+---+---+---+---+---+---+---+---+
0 1 2 3 4 5 6 7 8 9
-9 -8 -7 -6 -5 -4 -3 -2 -1
COMPUTERS[ 4 : 7 ] = UTE
COMPUTERS[ 2 : 5 : 2 ] = MU
COMPUTERS[-5 : 1 :-1 ] = UPM
COMPUTERS[ 4 ] = U
COMPUTERS[-4 :-6 :-1 ] = TU
COMPUTERS[ 2 :-3 : 1 ] = MPUT
COMPUTERS[ 2 :-3 :-1 ] =
COMPUTERS[ : :-1 ] = SRETUPMOC
COMPUTERS[-5 : ] = UTERS
COMPUTERS[-5 : 0 :-1 ] = UPMO
COMPUTERS[-5 : :-1 ] = UPMOC
COMPUTERS[-1 : 1 :-2 ] = SEUM
[Finished in 0.9s]
При использовании отрицательного шага обратите внимание, что ответ смещен вправо на 1.
Мой мозг, кажется, рад принять, что lst[start:end]
содержит start
-й пункт. Я мог бы даже сказать, что это «естественное предположение».
Но иногда возникает сомнение, и мой мозг просит заверить, что он не содержит end
-го элемента.
В эти моменты я полагаюсь на эту простую теорему:
for any n, lst = lst[:n] + lst[n:]
Это симпатичное свойство говорит мне, что lst[start:end]
не содержит end
-й элемент, потому что он находится в lst[end:]
.
Обратите внимание, что эта теорема верна для любого n
вообще. Например, вы можете проверить, что
lst = range(10)
lst[:-42] + lst[-42:] == lst
возвращается True
.
На мой взгляд, вы лучше поймете и запомните нотацию Python для разрезания строк, если посмотрите на нее следующим образом (читайте дальше).
Давайте работать со следующей строкой ...
azString = "abcdefghijklmnopqrstuvwxyz"
Для тех, кто не знает, вы можете создать любую подстроку, azString
используя обозначениеazString[x:y]
Исходя из других языков программирования, это когда здравый смысл нарушается. Что такое х и у?
Мне пришлось сесть и запустить несколько сценариев в своем поиске техники запоминания, которая поможет мне вспомнить, что такое x и y, и поможет мне правильно нарезать строки с первой попытки.
Мой вывод заключается в том, что x и y следует рассматривать как граничные индексы, которые окружают строки, которые мы хотим добавить. Таким образом, мы должны видеть выражение как azString[index1, index2]
или даже более ясным, какazString[index_of_first_character, index_after_the_last_character]
.
Вот пример визуализации этого ...
Letters a b c d e f g h i j ...
↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
┊ ┊
Indexes 0 1 2 3 4 5 6 7 8 9 ...
┊ ┊
cdefgh index1 index2
Поэтому все, что вам нужно сделать, это установить index1 и index2 в значения, которые будут окружать желаемую подстроку. Например, чтобы получить подстроку "cdefgh", вы можете использоватьazString[2:8]
, потому что индекс слева от «c» равен 2, а индекс справа от «h» равен 8.
Помните, что мы устанавливаем границы. И эти границы - это позиции, где вы можете поместить несколько скобок, которые будут обернуты вокруг подстроки, как это ...
ab [ cdefgh ] ij
Этот трюк работает постоянно и его легко запомнить.
Большинство предыдущих ответов проясняют вопросы о записи срезов.
Расширенный синтаксис индексации, используемый для нарезки aList[start:stop:step]
, и основные примеры:
Больше примеров нарезки: 15 расширенных ломтиков
В Python наиболее простой формой для нарезки является следующее:
l[start:end]
где l
- некоторая коллекция, start
это инклюзивный индекс и end
эксклюзивный индекс.
In [1]: l = list(range(10))
In [2]: l[:5] # First five elements
Out[2]: [0, 1, 2, 3, 4]
In [3]: l[-5:] # Last five elements
Out[3]: [5, 6, 7, 8, 9]
При нарезке с начала вы можете опустить нулевой индекс, а при срезании до конца вы можете опустить конечный индекс, так как он избыточен, поэтому не будьте многословны:
In [5]: l[:3] == l[0:3]
Out[5]: True
In [6]: l[7:] == l[7:len(l)]
Out[6]: True
Отрицательные целые числа полезны при выполнении смещений относительно конца коллекции:
In [7]: l[:-1] # Include all elements but the last one
Out[7]: [0, 1, 2, 3, 4, 5, 6, 7, 8]
In [8]: l[-3:] # Take the last three elements
Out[8]: [7, 8, 9]
Можно предоставить индексы, которые выходят за границы при нарезке, такие как:
In [9]: l[:20] # 20 is out of index bounds, and l[20] will raise an IndexError exception
Out[9]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [11]: l[-20:] # -20 is out of index bounds, and l[-20] will raise an IndexError exception
Out[11]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Имейте в виду, что результатом нарезки коллекции является совершенно новая коллекция. Кроме того, при использовании обозначений срезов в назначениях длина назначений срезов не обязательно должна быть одинаковой. Значения до и после назначенного среза будут сохранены, а коллекция будет уменьшаться или увеличиваться, чтобы содержать новые значения:
In [16]: l[2:6] = list('abc') # Assigning fewer elements than the ones contained in the sliced collection l[2:6]
In [17]: l
Out[17]: [0, 1, 'a', 'b', 'c', 6, 7, 8, 9]
In [18]: l[2:5] = list('hello') # Assigning more elements than the ones contained in the sliced collection l [2:5]
In [19]: l
Out[19]: [0, 1, 'h', 'e', 'l', 'l', 'o', 6, 7, 8, 9]
Если вы пропустите начальный и конечный индексы, вы создадите копию коллекции:
In [14]: l_copy = l[:]
In [15]: l == l_copy and l is not l_copy
Out[15]: True
Если начальный и конечный индексы опущены при выполнении операции присваивания, весь контент коллекции будет заменен копией того, на что есть ссылки:
In [20]: l[:] = list('hello...')
In [21]: l
Out[21]: ['h', 'e', 'l', 'l', 'o', '.', '.', '.']
Помимо базовой нарезки, также можно применять следующие обозначения:
l[start:end:step]
где l
- коллекция, start
инклюзивный индекс, end
эксклюзивный индекс и step
шаг, который можно использовать для ввода каждого n-го элемента l
.
In [22]: l = list(range(10))
In [23]: l[::2] # Take the elements which indexes are even
Out[23]: [0, 2, 4, 6, 8]
In [24]: l[1::2] # Take the elements which indexes are odd
Out[24]: [1, 3, 5, 7, 9]
Использование step
предоставляет полезную хитрость для обращения коллекции в Python:
In [25]: l[::-1]
Out[25]: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
Также можно использовать отрицательные целые числа для step
следующего примера:
In[28]: l[::-2]
Out[28]: [9, 7, 5, 3, 1]
Однако использование отрицательного значения для step
может стать очень запутанным. Кроме того, для того , чтобы быть вещим , следует избегать использования start
, end
и step
в одном срезе. В случае, если это требуется, подумайте о том, чтобы сделать это в двух заданиях (одно для нарезки, а другое для продвижения).
In [29]: l = l[::2] # This step is for striding
In [30]: l
Out[30]: [0, 2, 4, 6, 8]
In [31]: l = l[1:-1] # This step is for slicing
In [32]: l
Out[32]: [2, 4, 6]
Я хочу добавить один Hello, World! Пример, объясняющий основы ломтиков для самых начинающих. Это мне очень помогло.
Давайте составим список из шести значений ['P', 'Y', 'T', 'H', 'O', 'N']
:
+---+---+---+---+---+---+
| P | Y | T | H | O | N |
+---+---+---+---+---+---+
0 1 2 3 4 5
Теперь простейшими срезами этого списка являются его подсписки. Обозначение [<index>:<index>]
и ключ, чтобы прочитать это так:
[ start cutting before this index : end cutting before this index ]
Теперь, если вы сделаете часть [2:5]
списка выше, это произойдет:
| |
+---+---|---+---+---|---+
| P | Y | T | H | O | N |
+---+---|---+---+---|---+
0 1 | 2 3 4 | 5
Вы сделали разрез перед элементом с индексом 2
и еще один разрез перед элементом с индексом 5
. Таким образом, результатом будет срез между этими двумя разрезами, список ['T', 'H', 'O']
.
Ниже приведен пример индекса строки:
+---+---+---+---+---+
| H | e | l | p | A |
+---+---+---+---+---+
0 1 2 3 4 5
-5 -4 -3 -2 -1
str="Name string"
Пример нарезки: [начало: конец: шаг]
str[start:end] # Items start through end-1
str[start:] # Items start through the rest of the array
str[:end] # Items from the beginning through end-1
str[:] # A copy of the whole array
Ниже приведен пример использования:
print str[0] = N
print str[0:2] = Na
print str[0:7] = Name st
print str[0:7:2] = Nm t
print str[0:-1:2] = Nm ti
Если вы чувствуете, что отрицательные индексы в разрезании сбивают с толку, вот очень простой способ подумать об этом: просто замените отрицательный индекс на len - index
. Так, например, заменить -3 на len(list) - 3
.
Лучший способ проиллюстрировать, что секционирование выполняет внутренне, - просто показать это в коде, который реализует эту операцию:
def slice(list, start = None, end = None, step = 1):
# Take care of missing start/end parameters
start = 0 if start is None else start
end = len(list) if end is None else end
# Take care of negative start/end parameters
start = len(list) + start if start < 0 else start
end = len(list) + end if end < 0 else end
# Now just execute a for-loop with start, end and step
return [list[i] for i in range(start, end, step)]
Основной метод нарезки - определить начальную точку, точку остановки и размер шага - также известный как шаг.
Во-первых, мы создадим список значений для использования в нашей нарезке.
Создайте два списка для нарезки. Первый представляет собой числовой список от 1 до 9 (список А). Второй также является числовым списком от 0 до 9 (список B):
A = list(range(1, 10, 1)) # Start, stop, and step
B = list(range(9))
print("This is List A:", A)
print("This is List B:", B)
Индексируйте число 3 от A и число 6 от B.
print(A[2])
print(B[6])
Базовая нарезка
Расширенный синтаксис индексации, используемый для нарезки, - это aList [start: stop: step]. Аргумент start и шаг по умолчанию равны none - единственным обязательным аргументом является stop. Вы заметили, что это похоже на то, как диапазон использовался для определения списков A и B? Это связано с тем, что объект слайса представляет собой набор индексов, заданных диапазоном (начало, остановка, шаг). Документация по Python 3.4.
Как видите, определение только stop возвращает один элемент. Поскольку в начале по умолчанию ничего нет, это приводит к извлечению только одного элемента.
Важно отметить, что первым элементом является индекс 0, а не индекс 1. Именно поэтому мы используем 2 списка для этого упражнения. Элементы списка A нумеруются в соответствии с порядковым положением (первый элемент равен 1, второй элемент равен 2 и т. Д.), А элементы списка B представляют собой числа, которые будут использоваться для их индексации ([0] для первого элемента 0, так далее.).
С расширенным синтаксисом индексации мы получаем диапазон значений. Например, все значения извлекаются с помощью двоеточия.
A[:]
Чтобы получить подмножество элементов, необходимо определить начальную и конечную позиции.
Учитывая шаблон aList [start: stop], получить первые два элемента из списка А.
Я не думаю, что учебная схема Python (цитируемая в различных других ответах) хороша, так как это предложение работает для положительного шага, но не для отрицательного шага.
Это диаграмма:
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5 6
-6 -5 -4 -3 -2 -1
Из диаграммы, я ожидаю , a[-4,-6,-1]
чтобы быть , yP
но это ty
.
>>> a = "Python"
>>> a[2:4:1] # as expected
'th'
>>> a[-4:-6:-1] # off by 1
'ty'
То, что всегда работает, - это думать в символах или слотах и использовать индексирование как полуоткрытый интервал - справа, если положительный шаг, или слева, если отрицательный шаг
Таким образом, я могу думать , a[-4:-6:-1]
как a(-6,-4]
в интервальной терминологии.
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5
-6 -5 -4 -3 -2 -1
+---+---+---+---+---+---+---+---+---+---+---+---+
| P | y | t | h | o | n | P | y | t | h | o | n |
+---+---+---+---+---+---+---+---+---+---+---+---+
-6 -5 -4 -3 -2 -1 0 1 2 3 4 5