Документация по Python

Индексы списков и срез в Python

В: Документация по Python

Базовый срез

Для любого итерируемого объекта (например, строки, списка и т. Д.) Python позволяет срезать и вернуть подстроку или подсписок своих данных.

Формат для среза:

 iterable_name[start:stop:step]
 

где,

  • start первый индекс среза. По умолчанию 0 (индекс первого элемента)
  • stop последний индекс среза. По умолчанию len (индекс последнего элемента)
  • step шаг размера среза.(лучше объясняется в примере ниже)

Примеры:

a = "abcdef"
a             # так же как a[:] или a[::] если используются индексы по умолчанию всех трех индексов

>>>Out: 'abcdef'

a[-1]        

>>>Out: 'f'

a[:]         

>>>Out: 'abcdef'

a[::]

>>>Out: 'abcdef'

a[3:] 		# от элемента с индексом 3 до конца(размер шага имеет значение по умолчанию)

>>>Out: 'def'

a[:4]        # от начала (по умолчанию 0) до позиции 4 (не включая ее)

>>>Out: 'abcd' 


a[2:4]       # от позиции 2 до позиции 4 (не включая ее)

>>>Out: 'cd'

Кроме того, любой из вышеперечисленных срезов может использоваться с определенным размером шага:

a[::2]       # каждый второй элемент

>>>Out: 'ace'

a[1:4:2]     # от индекса 1 до индекса 4 (исключая), каждый второй элемент)

>>>Out: 'bd'

Индексы могут быть отрицательными, и в этом случае они вычисляются с конца последовательности

a[:-1]     #от нулевого индекса (по умолчанию) до 2ого индекса с конца (последний элемент - 1)

>>>Out: 'abcde' 

a[:-2]     # от нулевого индекса (по умолчанию) до 3его индекса с конца (последний элемент - 2)

>>>Out: 'abcd' 

a[-1:]     # от последнего элемента до конца (по умолчанию len()) 

>>>Out: 'f'

Размер шага также может быть отрицательным, в этом случае срез будет перебирать список в обратном порядке:

 a[3:1:-1]  # от индекса 2 до None (по умолчанию), в обратном порядке)
 
 >>>Out: 'dc'

Эта конструкция полезна для обращения итеративного

a[::-1]     # от последнего элемента (по умолчанию len()-1), до первого в обратном порядке (-1))

 >>>Out: 'fedcba'

Обратите внимание на то, что для отрицательных шагов по умолчанию end_index не None

a[5:None:-1] # эквивалентно a[::-1]

>>>Out: 'fedcba'

a[5:0:-1]    # от последнего элемента (индекс 5) до второго элемента (индекс 1)

>>>Out: 'fedcb'

Создание мелкой копии массива

Быстрый способ сделать копию массива (в отличие от присвоения переменной с другой ссылкой на исходный массив):

 arr[:]

 

Давайте рассмотрим синтаксис. [:] Означает , что start , end , и slice все опущены. Они по умолчанию равны 0 , len(arr) , и 1 , соответственно, что означает, что мы запрашиваем не будет иметь все элементы arr от начала до самого конца. На практике это выглядит примерно так:

arr = ['a', 'b', 'c']
copy = arr[:]
arr.append('d')
print(arr)

>>>Out: ['a', 'b', 'c', 'd']

print(copy)

>>>Out: ['a', 'b', 'c']

 

Как вы можете видеть, arr.append('d') добавил d к arr, но copy осталась неизменной!

Обратите внимание, что это делает неполную копию, и copy не идентичен arr.copy().

Разворот объекта

Вы можете использовать срезы для легкого разворота str , list или tuple (или в основном любой набор объектов , который реализует срез с параметром шага). Вот пример разворота строки, хотя это в равной степени относится и к другим типам, перечисленным выше:

s = 'reverse me!'
s[::-1]

>>>Out: '!em esrever'

Давайте быстро посмотрим на синтаксис. [::-1] означает , что срез должен быть с самого начала до конца строки (потому что start и end опущены) и шаг -1 означает , что он должен двигаться через колонну в обратном направлении.

Индексирование пользовательских классов: __getitem__, __setitem__ и __delitem__

class MultiIndexingList:
    def __init__(self, value):
        self.value = value

    def __repr__(self):
        return repr(self.value)

    def __getitem__(self, item):
        if isinstance(item, (int, slice)):
            return self.__class__(self.value[item])
        return [self.value[i] for i in item]

    def __setitem__(self, item, value):
        if isinstance(item, int):
            self.value[item] = value
        elif isinstance(item, slice):
            raise ValueError('Невозможно интерпретировать срез с множественным индексированием')
        else:
            for i in item:
                if isinstance(i, slice):
                    raise ValueError('Невозможно интерпретировать срез с множественным индексированием')
                self.value[i] = value

    def __delitem__(self, item):
        if isinstance(item, int):
            del self.value[item]
        elif isinstance(item, slice):
            del self.value[item]
        else:
            if any(isinstance(elem, slice) for elem in item):
                raise ValueError('Невозможно интерпретировать срез с множественным индексированием')
            item = sorted(item, reverse=True)
            for elem in item:
                del self.value[elem]

Это позволяет нарезать и индексировать для доступа к элементу:

a = MultiIndexingList([1,2,3,4,5,6,7,8])
a
>>>Out: [1, 2, 3, 4, 5, 6, 7, 8]

a[1,5,2,6,1]

>>>Out: [2, 6, 3, 7, 2]

a[4, 1, 5:, 2, ::2]

>>>Out: [5, 2, [6, 7, 8], 3, [1, 3, 5, 7]]


#       4|1-|----5:---|2-|-----::2-----   <-- определяет какой элемент пришел из какой позиции

Во время установки и удаления элементов допускает только запятые целочисленной индексации (без нарезки):

a[4] = 1000
a

>>>Out: [1, 2, 3, 4, 1000, 6, 7, 8]

a[2,6,1] = 100

>>>Out: [1, 100, 100, 4, 1000, 6, 100, 8]

del a[5]
a

>>>Out: [1, 100, 100, 4, 1000, 100, 8]

del a[4,2,5]
a

>>>Out: [1, 100, 4, 8] 

Назначение среза

Еще одна полезная функция, использующая срезы- это назначение срезов. Python позволяет назначать новые фрагменты для замены старых фрагментов списка за одну операцию.

Это означает, что если у вас есть список, вы можете заменить несколько членов в одном назначении:

lst = [1, 2, 3]
lst[1:3] = [4, 5]
print(lst)

>>>Out: [1, 4, 5]

Назначение также не должно совпадать по размеру, поэтому, если вы хотите заменить старый срез новым, отличающимся по размеру, вы можете:

lst = [1, 2, 3, 4, 5]
lst[1:4] = [6]
print(lst)

>>>Out: [1, 6, 5]

Также возможно использовать известный синтаксис среза для таких вещей, как замена всего списка:

lst = [1, 2, 3]
lst[:] = [4, 5, 6]
print(lst) 

>>>Out: [4, 5, 6]

Или только два последних члена:

lst = [1, 2, 3]
lst[-2:] = [4, 5, 6]
print(lst)

>>>Out: [1, 4, 5, 6]

Базовое индексирование

В списках Python первый элемент в списке можно получить по индексу 0

arr = ['a', 'b', 'c', 'd']
print(arr[0])

>>>Out: 'a'

Вы можете получить доступ к второму элементу в списке по индексу 1 , третий элемент по индексу 2 и так далее:

print(arr[1])

>>>Out: 'b'

print(arr[2])

>>>Out: 'c'

Вы также можете использовать отрицательные индексы для доступа к элементам в конце списка. например. индекс -1 даст вам последний элемент списка и индекс -2 даст вам второй до последнего элемента списка:

print(arr[-1])

>>>Out: 'd'

print(arr[-2])

>>>Out: 'c'

Если вы пытаетесь получить доступ к индексу , которого нет в списке, будет вызвана ошибка IndexError:

print arr[6]

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range 
Еще от кодкамп
Замечательно! Вы успешно подписались.
Добро пожаловать обратно! Вы успешно вошли
Вы успешно подписались на кодкамп.
Срок действия вашей ссылки истек.
Ура! Проверьте свою электронную почту на наличие волшебной ссылки для входа.
Успех! Ваша платежная информация обновлена.
Ваша платежная информация не была обновлена.