Мне нужно хорошее объяснение (ссылки - плюс) в нотации фрагмента Python.
Для меня эта нотация требует немного поднять.
Он выглядит чрезвычайно мощным, но я не совсем обнял его.
Мне нужно хорошее объяснение (ссылки - плюс) в нотации фрагмента Python.
Для меня эта нотация требует немного поднять.
Он выглядит чрезвычайно мощным, но я не совсем обнял его.
Это довольно просто на самом деле:
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)]
Объекты slice(stop)
также ведут себя немного по-разному в зависимости от количества аргументов, аналогично range()
, т.е. поддерживаются как slice(stop)
и slice(start, stop[, step])
. Чтобы пропустить указание заданного аргумента, можно использовать None
, так что, например, a[start:]
эквивалентно a[slice(start, None)]
или a[::-1]
эквивалентно a[slice(None, None, -1)]
.
В то время как :
-based нотация очень полезно для простой нарезки, явное использование slice()
объектов упрощает программную генерацию нарезания.
Python tutorial говорит об этом (прокрутите немного вниз, пока не дойдете до части, касающейся нарезки).
Диаграмма искусства ASCII также полезна для запоминания того, как работают срезы:
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5 6
-6 -5 -4 -3 -2 -1
Один из способов вспомнить, как работают срезы, - это учитывать индексы как указывающие между символами, а левый край первого символа нумеруется 0. Тогда правый край последнего символа строки из n символов имеет индекс n.
Перечисляя возможности, допускаемые грамматикой:
>>> 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)'
Ответы выше не обсуждают назначение срезов. Чтобы понять назначение срезов, полезно добавить еще одну концепцию в искусство 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 - это быстрый способ вычислительного доступа к частям ваших данных. На мой взгляд, быть даже промежуточным программистом на Python, это один из аспектов языка, с которым нужно быть знакомым.
Для начала определим несколько терминов:
start: начальный индекс среза, он будет включать элемент в этот индекс, если он не будет таким же, как stop, по умолчанию 0, то есть первый индекс. Если он отрицательный, это означает, что нужно начинать
n
элементов с конца.stop: конечный индекс среза, он не включает элемент в этот индекс, по умолчанию длина фрагментированной последовательности, то есть до и включая конец.
step: количество, на которое увеличивается индекс, по умолчанию равно 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, on")
Полная запись
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
.
Но вы можете передать отрицательное целое число, и список (или большинство других стандартных slicables) будет разрезан с конца до начала.
Таким образом, отрицательный срез изменит значения по умолчанию для start
и stop
!
Мне нравится поощрять пользователей читать источник, а также документацию. Исходный код для объектов среза и эта логика находятся здесь. Сначала мы определяем, является ли step
отрицательным:
step_is_negative = step_sign < 0;
Если это так, нижняя граница -1
означает, что мы -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
- значение по умолчанию для 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__
method (то, что делают квадратные скобки). Даже если вы не новичок в этом, он сохраняет ваш код более читабельным, так что другие, которые могут читать ваш код, могут более легко понять, что вы делаете.
Однако вы не можете просто назначить переменную целые числа, разделенные двоеточиями. Вам нужно использовать объект среза:
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 (исключая элемент в bth-индексе). Используйте правило индексирования выше и помните, что вы найдете только элементы в этом диапазоне:
-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]
Нашел эту отличную таблицу в 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 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]
- это просто вся строка.
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
Я использую метод "указательные точки между элементами", думая об этом сам, но один способ описать его, который иногда помогает другим получить это, это:
mylist[X:Y]
X - это индекс первого элемента, который вы хотите. Y - это индекс первого элемента, который вам не нужен.
Обозначение разреза Python:
a[start:end:step]
start
и end
отрицательные значения интерпретируются как относящиеся к концу последовательности.end
указывают позицию после включения последнего элемента.[+0:-0:1]
.start
и end
Обозначение распространяется на (numpy) матрицы и многомерные массивы. Например, чтобы разрезать целые столбцы, вы можете использовать:
m[::,0:2:] ## slice the first two columns
В срезах хранятся ссылки, а не копии элементов массива. Если вы хотите сделать отдельную копию массива, вы можете использовать deepcopy()
.
Вы также можете использовать назначение slice для удаления одного или нескольких элементов из списка:
r = [1, 'blah', 9, 8, 2, 3, 4]
>>> r[1:4] = []
>>> r
[1, 2, 3, 4]
Вот как я преподаю ломтики новичкам:
Понимание разницы между индексированием и нарезкой:
В 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.
Это просто для дополнительной информации... Рассмотрим список ниже
>>> 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]
Как правило, при написании кода с большим количеством жестко заданных значений индекса читаемость и обслуживание беспорядок. Например, если вы вернетесь к коду через год, вы будете взгляните на него и задайтесь вопросом, что вы думаете, когда вы его написали. Показанное решение это просто способ более четко указать, что делает ваш код на самом деле. В общем, встроенный 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.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
" после запятой работает во втором измерении.
#!/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)
Вы можете запустить этот script и поэкспериментировать с ним, ниже приведены некоторые образцы, которые я получил из script.
+---+---+---+---+---+---+---+---+---+
| 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
-th, потому что он находится в lst[end:]
.
Заметим, что эта теорема верна для любого n
вообще. Например, вы можете проверить, что
lst = range(10)
lst[:-42] + lst[-42:] == lst
возвращает True
.
Большинство предыдущих ответов проясняют вопросы об обозначениях срезов.
Синтаксис расширенного индексирования, используемый для нарезки, - aList[start:stop:step]
, и основные примеры:
Больше примеров нарезки: 15 расширенных фрагментов
Чтобы получить определенный фрагмент итерации (например, список), вот пример:
variable[number1:number2]
В этом примере положительное число для числа 1 - сколько компонентов вы снимаете спереди. Отрицательное число - это полная противоположность, сколько вы держите от конца. Положительное число для числа 2 указывает, сколько компонентов вы намерены сохранить с самого начала, а отрицательным является то, сколько вы намерены взлететь с конца. Это несколько противоречит интуитивному, но вы правы в предположении, что нарезка списка чрезвычайно полезна.
В 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
может привести к путанице. Кроме того, чтобы быть Pythonic, вы должны избегать использования 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
На мой взгляд, вы лучше поймете и запомните нотацию 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.
Помните, что мы устанавливаем границы. И эти границы - это позиции, в которые можно поместить несколько скобок, которые будут обернуты вокруг подстроки следующим образом...
a b [ c d e f g h ] i j
Этот трюк работает постоянно и его легко запомнить.
Если вы чувствуете, что отрицательные индексы в разрезании вводят в заблуждение, вот очень простой способ подумать об этом: просто замените отрицательный индекс на 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)]
Slice: - рядом с вашей ногой появляется змея. Он движется от невидимого до видимого. Наше видение показывает (как срез) только часть мира. Аналогично, фрагмент Python извлекает элементы, основанные на запуске и остановке. Мы берем фрагменты на многих типах в Python. Мы указываем необязательный первый индекс, необязательный последний индекс и необязательный шаг.
values[1:3] Index 1 through index 3.
values[2:-1] Index 2 through index one from last.
values[:2] Start through index 2.
values[2:] Index 2 through end.
values[::2] Start through end, skipping ahead 2 places each time.
вы можете получить хорошие примеры по ссылке ниже: пример обозначения фрагмента питона
Основной метод нарезки - определить начальную точку, точку остановки и размер шага - также известный как шаг.
Сначала мы создадим список значений, которые мы будем использовать при нарезке.
Создайте два списка для нарезки. Первый - это числовой список от 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], получить первые два элемента из списка А.