Индексы списков и слайсинг

Введение

Примеры

  • 11

    Базовая нарезка

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

    Формат для нарезки:

     iterable_name[start:stop:step]
     

    где,

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

    Примеры:

     a = "abcdef"
    a            # "abcdef" 
                 # Same as a[:] or a[::] since it uses the defaults for all three indices
    a[-1]        # "f"
    a[:]         # "abcdef" 
    a[::]        # "abcdef" 
    a[3:]        # "def" (from index 3, to end(defaults to size of iterable)) 
    a[:4]        # "abcd" (from beginning(default 0) to position 4 (excluded)) 
    a[2:4]       # "cd" (from position 2, to position 4 (excluded)) 
    
     

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

     a[::2]       # "ace" (every 2nd element)
    a[1:4:2]     # "bd" (from index 1, to index 4 (excluded), every 2nd element)
    
     

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

     a[:-1]     # "abcde" (from index 0 (default), to the second last element (last element - 1))
    a[:-2]     # "abcd" (from index 0 (default), to the third last element (last element -2))
    a[-1:]     # "f" (from the last element to the end (default len()) 
    
     

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

     a[3:1:-1]   # "dc" (from index 2 to None (default), in reverse order)
    
     

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

     a[::-1]     # "fedcba" (from last element (default len()-1), to first, in reverse order(-1))
    
     

    Обратите внимание на то, что для отрицательных шагов по умолчанию end_index не None (см https://codecamp.ru/a/12521981 )

     a[5:None:-1] # "fedcba" (this is equivalent to a[::-1])
    a[5:0:-1]    # "fedcb" (from the last element (index 5) to second element (index 1) 
  • 1

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

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

     arr[:]
    
     

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

    На практике это выглядит примерно так:

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

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

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

  • 5

    Поворот объекта

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

     s = 'reverse me!'
    s[::-1]    # '!em esrever'
    
     

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

  • 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('Cannot interpret slice with multiindexing')
            else:
                for i in item:
                    if isinstance(i, slice):
                        raise ValueError('Cannot interpret slice with multiindexing')
                    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('Cannot interpret slice with multiindexing')
                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-|----50:---|2-|-----::2-----   <-- indicated which element came from which index
    
     

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

     a[4] = 1000
    a
    # Out: [1, 2, 3, 4, 1000, 6, 7, 8]
    a[2,6,1] = 100
    a
    # 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] 
  • 2

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

    Еще одна полезная функция, использующая слайсы - это назначение слайсов. 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] 
  • 0

    Основное индексирование

    Списки Python являются 0 на основе т.е. первый элемент в списке можно получить по индексу 0

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

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

     print(arr[1])
    >> 'b'
    print(arr[2])
    >> 'c'
    
     

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

     print(arr[-1])
    >> 'd'
    print(arr[-2])
    >> 'c'
    
     

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

     print arr[6]
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    IndexError: list index out of range 

Синтаксис

Параметры

Примечания