2013-09-02 3 views
0

Я новичок в Python и пытался разобраться в нарезке списка.Почему список фрагментов в направлении справа налево возвращает пустой список?

На этот вопрос, возможно, был дан ответ (я попытался найти существующие вопросы и их ответы, но не смог найти то, что искал).

У меня есть список say, sample_list = [1,2,3,4,5,6,7].

Теперь, когда я пытаюсь получить доступ к:

печати sample_list [-2: 2]

или

печати sample_list [-3: -7]

В обоих случаях , Я получаю пустой список.

Не следует ли печатать по меньшей мере [6,7] или [5,6,7] соответственно, следуя соглашению слева направо?

Я знаю, я делаю что-то неправильно семантически.

(пытаясь напечатать список в справа налево направление?)

Я хотел бы понять логику пустого списка. Что здесь происходит?

Спасибо.

+0

Подсказка: что он печатает, если вы делаете 'sample_list [-2:]'? Также посмотрите [этот вопрос] (http://stackoverflow.com/questions/509211/the-python-slice-notation) –

+0

В 'sample_list [x: y]' индекс x является нижней границей и y является верхней. вы делаете 'sampe_list [-2: 2]', но в списке сначала появляется элемент с индексом 2. –

+0

@BurhanKhalid ссылка, безусловно, полезна. На самом деле, один из сообщений несколько отвечает на мои сомнения в том, почему я получаю пустые списки, а не ошибку: «Python доволен программисту (если предметов меньше, чем вы просите. Например, если вы попросите a [: - 2] и содержит только один элемент), вы получаете пустой список вместо ошибки. " – dkumar

ответ

3

Помните, что индексы начинаются с 0:

sample_list = [1,2,3,4,5,6,7] 
#    0 1 2 3 4 5 6 

Когда вы sample_list[-2:2], вы пытаетесь получить второй последний элемент к третьему элементу.

Но вы не можете просто перейти от отрицательного к положительному (если вы не добавите отрицательный шаг). Если вы хотите получить перевернутый список, а затем добавить step:

>>> print sample_list[2:-2][::-1] 
[5, 4, 3] 

Это та же самая проблема с вашим вторым примером. Вы пытаетесь идти в обратном направлении с отрицательными indicies, но вы не можете ... если ... добавить в отрицательном шаге !:

>>> print sample_list[-3:-7:-1] 
[5, 4, 3, 2] 
3

Если вы хотите порезать справа налево, что вам нужно для обеспечения отрицательного значения step: sample_list[-2:2:-1]. Это также изменит порядок значений.

И кусочек, как [-2:2], не имеет смысла. Если вы делаете sample_list[-2:2] в списке длины два, вы получите копию всего. В списке длиной три вы получите фрагмент с только средним элементом. Это только для списков длиной 4 или больше, вы получаете пустой фрагмент. Если они автоматически перевернутся, то некоторые из этих случаев будут неоднозначными.

Редактировать: Позвольте мне попытаться сделать более полное объяснение.

Синтаксис среза Python реализуется объектами slice. То есть L[start:stop:step] эквивалентен L[slice(start, stop, step)]. (Ну, вот как это работает на Python 3.Для обратной совместимости причин Python 2 также имеет более старый подход, используя __getslice__ и __setslice__ методы, но новый способ с slice объектами тоже работает.)

Когда вы берете кусок или список или кортеж, вы всегда получаете элементы, начиная с индекс start и продолжение до элемента непосредственно перед stop. Параметр step описывает размер выполненных шагов: 2 означает каждое другое значение, а -1 означает шаги в обратном порядке.

Другим способом мышления является то, что срез L[start:stop:step] почти эквивалентен пониманию списка [L[i] for i in range(start, stop, step)]. Различия заключаются только в том, что происходит, когда некоторые из значений отрицательны или не указаны.

Правило для обработки отрицательных значений легко (и это то же самое, что и для нерезкой индексации). Для start и stop просто добавьте длину последовательности к любому отрицательному значению. Таким образом, для положительных x и y срез L[-x:-y] в точности эквивалентен L[len(L)-x:len(L)-y]. Отрицательные значения step не преобразуются.

В отличие от обычного индексации, нарезка никогда не вызывает исключений для индексов вне диапазона. Если индексы недействительны, вы можете получить пустой результат или несколько меньше значений, чем запрашивал срез.

Не все аргументы для фрагмента требуются. A slice Конструктор объекта присваивает None значения по умолчанию для любого аргумента, не предоставленного. Что означают эти None s для start и stop, отличается в зависимости от знака step, а также от размеров списка, который нарезается.

Если step is None, он всегда обрабатывается, как если бы он был 1. Если step является положительным (или None), значение startNone обрабатывается так, как если бы оно было 0, а значение stopNone обрабатывается как len(L). Если step отрицательный, значение startNone обрабатывается как -1 и stop Значение None рассматривается как -len(L)-1.

Таким образом, чтобы обвести на ваш вопрос, когда вы делаете срез sample_list[-2:2], происходит несколько вещей:

Первый выключен, slice объект создается, как если бы вы сделали slice(-2, 2). Этот объект среза будет иметь stepNone, так как вы не указали третье значение.

Далее slice передается в список и значения интерпретируются. С step был None, используется значение по умолчанию 1. Поскольку start отрицательный, к нему добавляется длина списка.

И, наконец, результаты вычисляются. Для вашего списка примеров с семью значениями вы получите эквивалент [sample_list[i] for i in range(5, 2, 1)]. Поскольку диапазон пуст, срез тоже.

В зависимости от того, что вы хотели, вы можете исправить это несколькими способами.Вы можете оставить это, и вы получите результаты только для очень коротких списков источников, где len(L)-2 меньше, чем 2. В качестве альтернативы вы можете поменять порядок своих первых двух аргументов и получить результат [3,4,5]. Или вы можете добавить отрицательный step и срез справа налево, в результате получится [6, 5, 4].

Смежные вопросы