Pergunta

Preciso de uma boa explicação (referências são um sinal de mais) em Python fatia de notação.

Para mim, esta notação precisa de um pouco de pegar.

Parece extremamente poderoso, mas eu não tenho muito tenho a minha cabeça em torno dela.

Foi útil?

Solução

É realmente simples: realmente:

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

Há também o step valor, que pode ser usado com qualquer um dos itens acima:

a[start:stop:step] # start through not past stop, by step

O ponto principal a lembrar é que o :stop o valor representa o primeiro valor que é não Na fatia selecionada. Então, a diferença entre stop e start é o número de elementos selecionados (se step é 1, o padrão).

O outro recurso é que start ou stop talvez um negativo Número, o que significa que conta do final da matriz em vez do começo. Então:

a[-1]    # last item in the array
a[-2:]   # last two items in the array
a[:-2]   # everything except the last two items

De forma similar, step pode ser um número negativo:

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

O Python é gentil com o programador, se houver menos itens do que você solicita. Por exemplo, se você pedir a[:-2] e a Contém apenas um elemento, você obtém uma lista vazia em vez de um erro. Às vezes, você prefere o erro, então deve estar ciente de que isso pode acontecer.

Relação a slice() objeto

O operador de fatiamento [] está realmente sendo usado no código acima com um slice() objeto usando o : notação (que só é válida dentro []), ou seja:

a[start:stop:step]

é equivalente a:

a[slice(start, stop, step)]

Os objetos de fatia também se comportam um pouco diferente, dependendo do número de argumentos, da mesma forma range(), ou seja, ambos slice(stop) e slice(start, stop[, step]) são suportados. Para pular especificando um determinado argumento, pode -se usar None, para que, por exemplo, a[start:] é equivalente a a[slice(start, None)] ou a[::-1] é equivalente a a[slice(None, None, -1)].

Enquanto o :-A notação baseada é muito útil para fatias simples, o uso explícito de slice() Objetos simplifica a geração programática de fatias.

Outras dicas

o Tutorial Python fala sobre isso (role para baixo até chegar à parte sobre fatiar).

O diagrama de arte ASCII também é útil para lembrar como as fatias funcionam:

 +---+---+---+---+---+---+
 | P | y | t | h | o | n |
 +---+---+---+---+---+---+
 0   1   2   3   4   5   6
-6  -5  -4  -3  -2  -1

Uma maneira de lembrar como as fatias funcionam para pensar nos índices como apontando entre caracteres, com a borda esquerda do primeiro caractere numerado 0. Então a borda direita do último personagem de uma sequência de n caracteres tem índice n.

Enumiando as possibilidades permitidas pela gramática:

>>> 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]]

Claro se (high-low)%stride != 0, então o ponto final será um pouco menor que high-1.

Se stride é negativo, a ordem muda um pouco desde que estamos contando:

>>> 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]]

O fatiamento estendido (com vírgulas e elipses) é usado principalmente apenas por estruturas de dados especiais (como o Numpy); As seqüências básicas não as suportam.

>>> class slicee:
...     def __getitem__(self, item):
...         return repr(item)
...
>>> slicee()[0, 1:2, ::5, ...]
'(0, slice(1, 2, None), slice(None, None, 5), Ellipsis)'

As respostas acima não discutem a atribuição de fatias. Para entender a atribuição de fatias, é útil adicionar outro conceito à arte 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']

Uma heurística é, para uma fatia de zero a n, pensar: "Zero é o começo, comece no começo e pegue n itens em uma lista".

>>> 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']

Outra heurística é: "Para qualquer fatia, substitua o começo por zero, aplique a heurística anterior para obter o final da lista e depois conte o primeiro número de volta para cortar os itens do começo"

>>> 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.

A primeira regra de atribuição de fatia é que, desde o corte retorna uma lista, atribuição de fatia requer uma lista (ou outro iterável):

>>> 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

A segunda regra de atribuição de fatia, que você também pode ver acima, é que qualquer parte da lista seja retornada pela Indexação de fatias, essa é a mesma parte que é alterada pela atribuição de fatias:

>>> p[2:4]
 ['T','h']
>>> p[2:4] = ['t','r']
>>> p
 ['P','y','t','r','o','n']

A terceira regra de atribuição de fatia é que a lista atribuída (iterável) não precisa ter o mesmo comprimento; A fatia indexada é simplesmente cortada e substituída em massa pelo que estiver sendo atribuído:

>>> 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']

A parte mais complicada a se acostumar é a atribuição de fatias esvaziadas. Usando 1 e 2 heurísticos, é fácil entender indexação uma fatia vazia:

>>> 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]
 []

E então, depois de ver isso, a atribuição de fatia para a fatia vazia também faz sentido:

>>> 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

Observe que, como não estamos alterando o segundo número da fatia (4), os itens inseridos sempre se empilham contra o 'O', mesmo quando estamos atribuindo à fatia vazia. Portanto, a posição para a atribuição de fatia vazia é a extensão lógica das posições para as atribuições de fatia não vazia.

Fazendo backup um pouco, o que acontece quando você continua com nossa procissão de contar a fatia começando?

>>> 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]
 []

Com fatiamento, quando terminar, terminar; Não começa a cortar para trás. No Python, você não obtém avanços negativos, a menos que os peça explicitamente usando um número negativo.

>>> p[5:3:-1]
 ['n','o']

Existem algumas consequências estranhas para a regra "Quando terminar, terminar":

>>> 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

De fato, em comparação com a indexação, o fatiamento do Python é bizarramente à prova de erros:

>>> p[100:200]
 []
>>> p[int(2e99):int(1e99)]
 []

Isso pode ser útil às vezes, mas também pode levar a um comportamento um tanto estranho:

>>> 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']

Dependendo do seu aplicativo, isso pode ... ou não ... seja o que você esperava por lá!


Abaixo está o texto da minha resposta original. Tem sido útil para muitas pessoas, então eu não queria excluí -lo.

>>> 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]

Isso também pode esclarecer a diferença entre fatiamento e indexação.

Explique a notação de fatia de Python

Em suma, os dois pontos (:) na notação subscrita (subscriptable[subscriptarg]) faça notação de fatia - que tem os argumentos opcionais, start, stop, step:

sliceable[start:stop:step]

O fatiamento do Python é uma maneira computacionalmente rápida de acessar metodicamente partes de seus dados. Na minha opinião, para ser um programador intermediário de Python, é um aspecto da linguagem com a qual é necessário estar familiarizado.

Definições importantes

Para começar, vamos definir alguns termos:

começar: O índice de início da fatia, ele incluirá o elemento neste índice, a menos que seja o mesmo que Pare, padrão para 0, ou seja, o primeiro índice. Se for negativo, significa começar n itens do final.

Pare: o índice final da fatia, ele faz não Inclua o elemento neste índice, os padrões de comprimento da sequência que estão sendo cortados, ou seja, até e incluindo o final.

degrau: A quantidade pela qual o índice aumenta, padrão para 1. Se for negativo, você está cortando o iterável ao contrário.

Como funciona a indexação

Você pode fazer qualquer um desses números positivos ou negativos. O significado dos números positivos é direto, mas para números negativos, assim como os índices em python, você conta para trás a partir do final para o começar e Pare, e para o degrau, você simplesmente diminui seu índice. Este exemplo é Do tutorial da documentação, mas eu o modifiquei um pouco para indicar qual item em uma sequência cada referências de índice:

 +---+---+---+---+---+---+
 | P | y | t | h | o | n |
 +---+---+---+---+---+---+
   0   1   2   3   4   5 
  -6  -5  -4  -3  -2  -1

Como funciona o fatiamento

Para usar a notação de fatia com uma sequência que a suporta, você deve incluir pelo menos um cólon nos colchetes que seguem a sequência (que na verdade implementar o __getitem__ Método da sequência, de acordo com o modelo de dados python.)

A notação de fatia funciona assim:

sequence[start:stop:step]

E lembre -se de que existem padrões para começar, Pare, e degrau, para acessar os padrões, basta deixar de fora o argumento.

Notação de fatia para obter os últimos nove elementos de uma lista (ou qualquer outra sequência que a suporta, como uma string) seria assim:

my_list[-9:]

Quando vejo isso, li a parte entre os colchetes como "9º do final, até o final". (Na verdade, eu abreviado mentalmente como "-9, on")

Explicação:

A notação completa é

my_list[-9:None:None]

e para substituir os padrões (na verdade quando step é negativo, stopO padrão é -len(my_list) - 1, assim None Pois Stop realmente significa apenas que vai para qualquer passo final para levar para):

my_list[-9:len(my_list):1]

o cólon, :, é o que diz Python que você está dando uma fatia e não um índice regular. É por isso que a maneira idiomática de fazer uma cópia superficial das listas no Python 2 é

list_copy = sequence[:]

E limpá -los está com:

del my_list[:]

(Python 3 recebe um list.copy e list.clear método.)

Quando step é negativo, os padrões para start e stop mudança

Por padrão, quando o step O argumento está vazio (ou None), é atribuído a +1.

Mas você pode passar em um número inteiro negativo e a lista (ou a maioria dos outros slicables padrão) será cortada do final ao início.

Assim, uma fatia negativa mudará os padrões para start e stop!

Confirmando isso na fonte

Gosto de incentivar os usuários a ler a fonte e a documentação. o Código -fonte para objetos de fatia e esta lógica é encontrada aqui. Primeiro determinamos se step é negativo:

 step_is_negative = step_sign < 0;

Nesse caso, o limite inferior é -1 Significando que cortamos todo o caminho até o início, e o limite superior é o comprimento menos 1, o que significa que começamos no final. (Observe que a semântica deste -1 é diferente a partir de um -1 que os usuários podem passar os índices em python indicando o último item.)

if (step_is_negative) {
    lower = PyLong_FromLong(-1L);
    if (lower == NULL)
        goto error;

    upper = PyNumber_Add(length, lower);
    if (upper == NULL)
        goto error;
}

Por outro lado step é positivo, e o limite inferior será zero e o limite superior (que subimos, mas não incluindo) o comprimento da lista fatiada.

else {
    lower = _PyLong_Zero;
    Py_INCREF(lower);
    upper = length;
    Py_INCREF(upper);
}

Então, podemos precisar aplicar os padrões para start e stop - o padrão então para start é calculado como o limite superior quando step é negativo:

if (self->start == Py_None) {
    start = step_is_negative ? upper : lower;
    Py_INCREF(start);
}

e stop, o limite inferior:

if (self->stop == Py_None) {
    stop = step_is_negative ? lower : upper;
    Py_INCREF(stop);
}

Dê às suas fatias um nome descritivo!

Você pode achar útil separar a formação da fatia de passá -la para o list.__getitem__ método (Isso é o que os colchetes fazem). Mesmo se você não é novo, ele mantém seu código mais legível para que outras pessoas que possam ter que ler seu código podem entender com mais facilidade o que você está fazendo.

No entanto, você não pode simplesmente atribuir alguns números inteiros separados por dois pontos a uma variável. Você precisa usar o objeto Slice:

last_nine_slice = slice(-9, None)

O segundo argumento, None, é necessário, para que o primeiro argumento seja interpretado como o start argumento Caso contrário, seria o stop argumento.

Você pode passar o objeto Slice para sua sequência:

>>> list(range(100))[last_nine_slice]
[91, 92, 93, 94, 95, 96, 97, 98, 99]

É interessante que os intervalos também levem fatias:

>>> range(100)[last_nine_slice]
range(91, 100)

Considerações de memória:

Como fatias de listas de python criam novos objetos na memória, outra função importante a ser ciente itertools.islice. Normalmente, você deseja iterar por uma fatia, não apenas criá -la estaticamente na memória. islice é perfeito para isso. Uma ressalva, não suporta argumentos negativos para start, stop, ou step, por isso, se esse for um problema, pode ser necessário calcular índices ou reverter o itemerável com antecedência.

length = 100
last_nine_iter = itertools.islice(list(range(length)), length-9, None, 1)
list_last_nine = list(last_nine_iter)

e agora:

>>> list_last_nine
[91, 92, 93, 94, 95, 96, 97, 98, 99]

O fato de as fatias de lista fazer uma cópia é um recurso das próprias listas. Se você estiver cortando objetos avançados, como um DataFrame de pandas, ele poderá retornar uma visualização no original e não uma cópia.

E algumas coisas que não foram imediatamente óbvias para mim quando vi pela primeira vez a sintaxe do fatiamento:

>>> x = [1,2,3,4,5,6]
>>> x[::-1]
[6,5,4,3,2,1]

Maneira fácil de reverter sequências!

E se você quisesse, por algum motivo, cada segundo item na sequência invertida:

>>> x = [1,2,3,4,5,6]
>>> x[::-2]
[6,4,2]

No Python 2.7

Fluing em 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).

Entender a atribuição do índice é muito importante.

In forward direction, starts at 0 and ends at len-1

In backward direction, starts at -1 and ends at -len

Quando você diz [A: B: C], está dizendo dependendo do sinal de C (para frente ou para trás), comece em A e termine em B (excluindo o elemento no índice BTH). Use a regra de indexação acima e lembre -se de que você encontrará apenas elementos nesse intervalo:

-len, -len+1, -len+2, ..., 0, 1, 2,3,4 , len -1

Mas esse intervalo continua em ambas as direções infinitamente:

...,-len -2 ,-len-1,-len, -len+1, -len+2, ..., 0, 1, 2,3,4 , len -1, len, len +1, len+2 , ....

Por exemplo:

             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

Se a sua escolha de A, B e C permitir sobreposição com o intervalo acima ao percorrer o uso de regras para A, B, C acima, você receberá uma lista com elementos (tocados durante o Traversal) ou você receberá uma lista vazia.

Uma última coisa: se A e B são iguais, também você recebe uma lista vazia:

>>> 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]

Encontrei esta ótima mesa em 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)

Depois de usá -lo um pouco, percebo que a descrição mais simples é que é exatamente o mesmo que os argumentos em um for ciclo...

(from:to:step)

Qualquer um deles é opcional:

(:to:step)
(from::step)
(from:to)

Em seguida, a indexação negativa só precisa que você adicione o comprimento da string aos índices negativos para entendê -la.

Isso funciona para mim de qualquer maneira ...

Acho mais fácil lembrar como funciona e, em seguida, posso descobrir qualquer combinação específica de início/parada/etapa.

É instrutivo entender range() primeiro:

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

Começar de start, incremento por step, não alcance stop. Muito simples.

A coisa a lembrar sobre o passo negativo é que stop é sempre o fim excluído, seja maior ou menor. Se você quer a mesma fatia em ordem oposta, é muito mais limpo fazer a reversão separadamente: por exemplo 'abcde'[1:-2][::-1] Fiz um char da esquerda, dois da direita e depois reverte. (Veja também reversed().)

O fatiamento de sequência é o mesmo, exceto que primeiro normaliza os índices negativos, e nunca pode sair da sequência:

FAÇAM: O código abaixo tinha um bug com "nunca saia da sequência" quando abs (etapa)> 1; EU acho Eu corrigi para estar correto, mas é difícil de entender.

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]

Não se preocupe com o is None Detalhes - Lembre -se de que omitir start e/ou stop Sempre faz a coisa certa para lhe dar toda a sequência.

A normalização dos índices negativos permite que o início e/ou pare sejam contados do final de forma independente: 'abcde'[1:-2] == 'abcde'[1:3] == 'bc' apesar de range(1,-2) == []. A normalização às vezes é pensada como "módulo o comprimento", mas observe que adiciona o comprimento apenas uma vez: por exemplo 'abcde'[-53:42] é apenas a corda inteira.

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   :
|--------------->
    <---------------|

Espero que isso ajude você a modelar a lista em Python.

Referência: http://wiki.python.org/moin/movingtopythonfromotherlanguages

Eu uso o método "um índice de pontos entre elementos" de pensar sobre ele mesmo, mas uma maneira de descrevê -lo que às vezes ajuda os outros a entender é isso:

mylist[X:Y]

X é o índice do primeiro elemento que você deseja.
Y é o índice do primeiro elemento que você não querer.

Notação de fatiamento de python:

a[start:end:step]
  • Por start e end, valores negativos são interpretados como sendo relativos ao final da sequência.
  • Índices positivos para end indicar a posição depois o último elemento a ser incluído.
  • Os valores em branco são padronizados da seguinte forma: [+0:-0:1].
  • Usar uma etapa negativa reverte a interpretação de start e end

A notação se estende a matrizes (Numpy) e matrizes multidimensionais. Por exemplo, para cortar colunas inteiras que você pode usar:

m[::,0:2:] ## slice the first two columns

As fatias mantêm referências, não cópias, dos elementos da matriz. Se você quiser fazer uma cópia separada uma matriz, você pode usar deepcopy().

Você também pode usar a atribuição de fatia para remover um ou mais elementos de uma lista:

r = [1, 'blah', 9, 8, 2, 3, 4]
>>> r[1:4] = []
>>> r
[1, 2, 3, 4]

É assim que eu ensino fatias para iniciantes:

Entendendo a diferença entre indexação e fatiamento:

O Wiki Python tem essa imagem incrível que distingue claramente a indexação e o fatiamento.

enter image description here

É uma lista com 6 elementos. Para entender melhor o fatiamento, considere essa lista como um conjunto de seis caixas colocadas juntas. Cada caixa tem um alfabeto.

A indexação é como lidar com o conteúdo da caixa. Você pode verificar o conteúdo de qualquer caixa. Mas você não pode verificar o conteúdo de várias caixas de uma só vez. Você pode até substituir o conteúdo da caixa. Mas você não pode colocar 2 bolas em 1 caixa ou substituir 2 bolas por vez.

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

Cortar é como lidar com as próprias caixas. Você pode pegar a primeira caixa e colocá -la em outra mesa. Para pegar a caixa, tudo o que você precisa saber é a posição de iniciação e final da caixa.

Você pode até pegar 3 primeiras caixas ou 2 caixas ou todas as caixas entre 1 e 4. Portanto, você pode escolher qualquer conjunto de caixas se souber o início e o fim. Essas posições são chamadas de posições de início e parada.

O interessante é que você pode substituir várias caixas de uma só vez. Além disso, você pode colocar várias caixas onde quer que quiser.

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']

Cortando com etapa:

Até agora, você escolheu caixas continuamente. Mas algumas vezes você precisa pegar discretamente. Por exemplo, você pode pegar cada segunda caixa. Você pode até pegar a cada terceira caixa do final. Este valor é chamado de tamanho de etapa. Isso representa a lacuna entre seus captadores sucessivos. O tamanho da etapa deve ser positivo se você estiver escolhendo caixas do início ao fim e vice -versa.

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]: []

Como o Python descobre os parâmetros ausentes:

Ao cortar se você deixar de fora algum parâmetro, o Python tenta descobrir isso automaticamente.

Se você verificar o código -fonte do cpython, encontrará uma função chamada Pyslice_getIndicesex, que descobre os índices em uma fatia para qualquer parâmetros. Aqui está o código equivalente lógico em Python.

Esta função leva um objeto Python e parâmetros opcionais para fatiar e as devoluções iniciam, pare, etapa e comprimento da fatia para a fatia solicitada.

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)

Esta é a inteligência que está presente por trás das fatias. Como o Python possui uma função embutida chamada Slice, você pode passar alguns parâmetros e verificar como ele calcula inteligentemente os parâmetros ausentes.

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]

Observação: Este post está originalmente escrito no meu blog http://www.avilpage.com/2015/03/a-slice-of-python-intelligence-behind.html

Isso é apenas para algumas informações extras ... considere a lista abaixo

>>> l=[12,23,345,456,67,7,945,467]

Poucos outros truques para reverter a lista:

>>> 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]

Como regra geral, escrever código com muitos valores de índice codificados leva a uma confusão de legibilidade e manutenção. Por exemplo, se você voltar ao código um ano depois, verá e se perguntará o que estava pensando quando o escreveu. A solução mostrada é simplesmente uma maneira de declarar mais claramente o que seu código está realmente fazendo. Em geral, o slice embutido () cria um objeto de fatia que pode ser usado em qualquer lugar em que uma fatia seja permitida. Por exemplo:

>>> 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]

Se você tiver uma instância de fatia S, poderá obter mais informações sobre isso observando seus atributos S.Start, S.Stop e S.Step, respectivamente. Por exemplo:

>>> a = slice(10, 50, 2)
>>> a.start
10
>>> a.stop
50
>>> a.step
2
>>>

1. Notação de fatia

Para simplificar, lembre -se Slice tem apenas uma forma:

s[start:end:step]

E aqui está como funciona:

  • s: um objeto que pode ser cortado
  • start: primeiro índice a iniciar a iteração
  • end: Último índice, Observe que end o índice não será incluído na fatia resultante
  • step: escolha elemento a cada step índice

Outra coisa de importação: tudo start,end, step pode ser omitida! E se forem omitidos, seu valor padrão será usado: 0,len(s),1 adequadamente.

Portanto, possíveis variações são:

# 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[:]

Nota: Se start>=end(considerando apenas quando step>0), Python retornará uma fatia vazia [].

2. Armadilhas

A parte acima explica os principais recursos de como a fatia funciona, ela funcionará na maioria das ocasiões. No entanto, pode haver armadilhas que você deve observar, e essa parte as explica.

Índices negativos

A primeira coisa que confunde os alunos de Python é que O índice pode ser negativo! Não entrar em pânico: Índice negativo significa contar de costas.

Por exemplo:

s[-5:]    # start at the 5th index from the end of array, 
          # thus returns the last 5 elements
s[:-5]    # start at index 0, end until the 5th index from end of array, 
          # thus returns s[0:len(s)-5]

Etapa negativa

Tornar as coisas mais confusas é que step Pode ser negativo também!

Etapa negativa significa iterar a matriz para trás: do final para o início, com o índice final incluído e o índice de início excluído do resultado.

NOTA: Quando a etapa é negativa, o valor padrão para start para len(s)(enquanto end não é igual a 0, Porque s[::-1] contém s[0]). Por exemplo:

s[::-1]            # reversed slice
s[len(s)::-1]      # same as above, reversed slice
s[0:len(s):-1]     # empty list

Erro fora do alcance?

Surpreenda -se: O Slice não aumenta o IndexError quando o índice está fora do alcance!

Se o índice estiver fora de alcance, o Python tentará o seu melhor definir o índice para 0 ou len(s) De acordo com a situação. Por exemplo:

s[:len(s)+5]      # same as s[:len(s)]
s[-len(s)-5::]    # same as s[0:]
s[len(s)+5::-1]   # same as s[len(s)::-1], same as s[::-1]

3. Exemplos

Vamos terminar esta resposta com exemplos explica tudo o que discutimos:

# 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, 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 IndexError
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-15-79ffc22473a3> in <module>()
----> 1 s[11]

IndexError: list index out of range

As respostas acima não discutem o fatiamento de matriz multi-deve-se, o que é possível usando o famoso pacote Numpy:

O fatiamento também pode ser aplicado a matrizes multi-diário.

# 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]])

O ":2"Antes da vírgula opera na primeira dimensão e no"0:3:2"Após a vírgula opera na segunda dimensão.

#!/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)

Você pode executar esse script e experimentar, abaixo estão algumas amostras que recebi do 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]

Ao usar uma etapa negativa, observe que a resposta é deslocada para a direita por 1.

Meu cérebro parece feliz em aceitar isso lst[start:end] contém o start-th item. Eu posso até dizer que é uma 'suposição natural'.

Mas ocasionalmente uma dúvida se aproxima e meu cérebro pede garantia de que não contém o end-th elemento.

Nesses momentos em que confio neste teorema simples:

for any n,    lst = lst[:n] + lst[n:]

Esta bela propriedade me diz que lst[start:end] não contém o end-th item porque está em lst[end:].

Observe que este teorema é verdadeiro para qualquer n de forma alguma. Por exemplo, você pode verificar isso

lst = range(10)
lst[:-42] + lst[-42:] == lst

retorna True.

Em Python, a forma mais básica para fatiar é a seguinte:

l[start:end]

Onde l é alguma coleção, start é um índice inclusivo e end é um índice exclusivo.

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]

Ao cortar do início, você pode omitir o índice zero e, ao cortar até o final, você pode omitir o índice final, pois é redundante, por isso não seja detalhado:

In [5]: l[:3] == l[0:3]
Out[5]: True

In [6]: l[7:] == l[7:len(l)]
Out[6]: True

Inteiros negativos são úteis ao fazer compensações em relação ao final de uma coleção:

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 3 elements
Out[8]: [7, 8, 9]

É possível fornecer índices fora dos limites ao fatiar como:

In [9]: l[:20] # 20 is out of index bounds, 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, l[-20] will raise an IndexError exception
Out[11]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Lembre -se de que o resultado de cortar uma coleção é uma coleção totalmente nova. Além disso, ao usar a notação de fatia nas atribuições, o comprimento da atribuição de fatia não precisa ser o mesmo. Os valores antes e depois da fatia atribuída serão mantidos, e a coleção encolherá ou crescerá para conter os novos valores:

In [16]: l[2:6] = list('abc') # assigning less 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]

Se você omitir o índice de início e final, fará uma cópia da coleção:

In [14]: l_copy = l[:]

In [15]: l == l_copy and l is not l_copy
Out[15]: True

Se os índices de início e final forem omitidos ao executar uma operação de atribuição, todo o conteúdo da coleção será substituído por uma cópia do que é referenciado:

In [20]: l[:] = list('hello...')

In [21]: l
Out[21]: ['h', 'e', 'l', 'l', 'o', '.', '.', '.']

Além do fatiamento básico, também é possível aplicar a seguinte notação:

l[start:end:step]

Onde l é uma coleção, start é um índice inclusivo, end é um índice exclusivo, e step é um passo que pode ser usado para levar cada Nth item in 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]

Usando step Fornece um truque útil para reverter uma coleção em Python:

In [25]: l[::-1]
Out[25]: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

Também é possível usar números inteiros negativos para step Como o seguinte exemplo:

In[28]:  l[::-2]
Out[28]: [9, 7, 5, 3, 1]

No entanto, usando um valor negativo para step pode se tornar muito confuso. Além disso, para ser pitônico, você deve evitar usar start, end, e step em uma única fatia. Caso isso seja necessário, considere fazer isso em duas tarefas (uma para cortar e a outra para avançar).

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]

A maioria das respostas acima limpa sobre a notação de fatia. A sintaxe de indexação estendida usada para fatiar é aList[start:stop:step]Exemplos básicos são

enter image description here:

Mais exemplos de fatiamento: 15 fatias estendidas

O abaixo é o exemplo de índice de uma string

 +---+---+---+---+---+
 | H | e | l | p | A |
 +---+---+---+---+---+
 0   1   2   3   4   5
-5  -4  -3  -2  -1

str="Name string"

Exemplo de corte: [Iniciar: End: Etapa

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

Abaixo está o exemplo de uso

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

Quero adicionar um exemplo do Hello World que explique o básico das fatias para os próprios iniciantes. Isto me ajudou bastante.

Vamos ter uma lista com seis valores ['P', 'Y', 'T', 'H', 'O', 'N']:

+---+---+---+---+---+---+
| P | Y | T | H | O | N |
+---+---+---+---+---+---+
  0   1   2   3   4   5 

Agora, as fatias mais simples dessa lista são seus sublistas. A notação é [<index>:<index>] E a chave é ler assim:

[ start cutting before this index : end cutting before this index ]

Agora, se você fizer uma fatia [2:5] da lista acima, isso acontecerá:

        |           |
+---+---|---+---+---|---+
| P | Y | T | H | O | N |
+---+---|---+---+---|---+
  0   1 | 2   3   4 | 5 

Você fez um corte antes da o elemento com índice 2 e outro corte antes da o elemento com índice 5. Portanto, o resultado será uma fatia entre esses dois cortes, uma lista ['T', 'H', 'O'].

Na minha opinião, você entenderá e memorizará melhor a notação de corte de cordas do Python se olhar da seguinte maneira (continue).

Vamos trabalhar com a seguinte string ...

azString = "abcdefghijklmnopqrstuvwxyz"

Para quem não sabe, você pode criar qualquer substring de azString usando a notação azString[x:y]

Vindo de outras linguagens de programação, é aí que o senso comum é comprometido. O que são x e y?

Eu tive que me sentar e executar vários cenários em minha busca por uma técnica de memorização que me ajudará a lembrar o que X e Y são e me ajudarão a cortar as cordas corretamente na primeira tentativa.

Minha conclusão é que X e Y devem ser vistos como os índices de limite que estão ao redor das cordas que queremos extra. Então devemos ver a expressão como azString[index1, index2] ou ainda mais claro como azString[index_of_first_character, index_after_the_last_character].

Aqui está um exemplo de visualização disso ...

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

Portanto, tudo o que você precisa fazer para definir o index1 e o index2 para os valores que envolverão a substring desejada. Por exemplo, para obter a substring "CDefgh", você pode usar azString[2:8] Porque o índice no lado esquerdo de "C" é 2 e o do tamanho direito de "H" é 8.

Lembre -se de que estamos definindo os limites. E esses limites são as posições em que você pode colocar alguns colchetes que serão enrolados em torno da substring como esta ...

ab [ CDEFGH ] eu j

Esse truque funciona o tempo todo e é fácil de memorizar.

Se você sentir índices negativos em fatiar é confuso, aqui está uma maneira muito fácil de pensar sobre isso: apenas substitua o índice negativo por len - index. Por exemplo, substitua -3 por len(list) - 3.

A melhor maneira de ilustrar o que o fatiamento faz internamente é mostrá -lo em código que implementa esta operação:

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 for-loop with start, end and step
  return [list[i] for i in range(start, end, step)]

O basic técnica de retoque é definir o ponto de partida, o ponto de parada, e o tamanho do passo - também conhecida como o passo.

Primeiro, vamos criar uma lista de valores para uso em nossa corte.

Crie duas listas, a fatia, o primeiro é um valor numérico de 1 a 9 (Lista A).O segundo também é um valor numérico lista, de 0 a 9 (Lista B)

A = list(range(1,10,1)) # start,stop,step
B = list(range(9))

print("This is List A:",A)
print("This is List B:",B)

Índice de número 3 a partir de Um e o número 6 do B.

print(A[2])
print(B[6])

Básicas De Corte

Prorrogado de indexação sintaxe usada para fatiar é aList[start stop:: passo].O argumento início e o passo argumento padrão para nenhum, o único argumento obrigatório é parar.Observaste isso é semelhante à forma como eram usados para definir listas A e B?Isto é porque a fatia objeto representa o conjunto de índices especificados por faixa(iniciar, parar, passo).Python 3.4 documentação

Como você pode ver, a definição de parar apenas retorna um elemento.Desde o início o padrão é none, isso se traduz em recuperação de apenas um elemento.

É importante salientar, que o primeiro elemento de índice 0, e NÃO o índice de 1.É por isso que nós estamos usando 2 listas para esse exercício.Lista de elementos são numerados de acordo com a posição ordinal (o primeiro elemento é 1, o segundo elemento é 2, etc.), enquanto que a Lista B, com os elementos são os números que seriam utilizados para indexá-los ([0] para o primeiro elemento 0, etc.).

Com extensão de indexação de sintaxe, podemos obter um intervalo de valores.Por exemplo, todos os valores são obtidos com uma vírgula.

A[:]

Para obter um subconjunto de elementos, a iniciar e parar posições precisam ser definidos.

Dado o padrão de aList[start stop:stop], recuperar os dois primeiros elementos de Uma Lista

É fácil entender se poderíamos relacionar o fatiamento com range, que fornece os índices. Podemos categorizar o fatiamento nas duas categorias a seguir:


1. Sem passo ou passo> 0. por exemplo, [i:j] ou [i:j:k] (k> 0)

Suponha que a sequência seja s=[1,2,3,4,5].

  • E se 0<i<len(s) e 0<j<len(s), então [i:j:k] -> range(i,j,k)

Por exemplo, [0:3:2] -> range(0,3,2) -> 0, 2

  • E se i>len(s) ou j>len(s), então i=len(s) ou j=len(s)

Por exemplo, [0:100:2] -> range(0,len(s),2) -> range(0,5,2) -> 0, 2, 4

  • E se i<0 ou j<0, então i=max(0,len(s)+i) ou j=max(0,len(s)+j)

Por exemplo, [0:-3:2] -> range(0,len(s)-3,2) -> range(0,2,2) -> 0

Para outro exemplo, [0:-1:2] -> range(0,len(s)-1,2) -> range(0,4,2) -> 0, 2

  • E se i não é especificado, então i=0

Por exemplo, [:4:2] -> range(0,4,2) -> range(0,4,2) -> 0, 2

  • E se j não é especificado, então j=len(s)

Por exemplo, [0::2] -> range(0,len(s),2) -> range(0,5,2) -> 0, 2, 4


2. Etapa <0. por exemplo, [i:j:k] (k <0)

Suponha que a sequência seja s=[1,2,3,4,5].

  • E se 0<i<len(s) e 0<j<len(s), então [i:j:k] -> range(i,j,k)

Por exemplo, [5:0:-2] -> range(5,0,-2) -> 5, 3, 1

  • E se i>len(s) ou j>len(s), então i=len(s)-1 ou j=len(s)-1

Por exemplo, [100:0:-2] -> range(len(s)-1,0,-2) -> range(4,0,-2) -> 4, 2

  • E se i<0 ou j<0, então i=max(-1,len(s)+i) ou j=max(-1,len(s)+j)

Por exemplo, [-2:-10:-2] -> range(len(s)-2,-1,-2) -> range(3,-1,-2) -> 3, 1

  • E se i não é especificado, então i=len(s)-1

Por exemplo, [:0:-2] -> range(len(s)-1,0,-2) -> range(4,0,-2) -> 4, 2

  • E se j não é especificado, então j=-1

Por exemplo, [2::-2] -> range(2,-1,-2) -> 2, 0

Para outro exemplo, [::-1] -> range(len(s)-1,-1,-1) -> range(4,-1,-1) -> 4, 3, 2, 1, 0


Resumindo

enter image description here

Eu não acho que o Tutorial Python O diagrama (citado em várias outras respostas) é bom, pois essa sugestão funciona para um passo positivo, mas não faz um passo negativo.

Este é o diagrama:

 +---+---+---+---+---+---+
 | P | y | t | h | o | n |
 +---+---+---+---+---+---+
 0   1   2   3   4   5   6
-6  -5  -4  -3  -2  -1

Do diagrama, espero a[-4,-6,-1] ser yP Mas isso é ty.

>>> a = "Python"
>>> a[2:4:1] # as expected
'th'
>>> a[-4:-6:-1] # off by 1
'ty'

O que sempre funciona é pensar em caracteres ou slots e usar a indexação como intervalo semi-aberto-o seu passo positivo, se o passo positivo, se o squide negativo.

Dessa forma, eu posso pensar em a[-4:-6:-1] Como a(-6,-4] em terminologia do intervalo.

 +---+---+---+---+---+---+
 | 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  
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top