O que é :: (dois pontos duplos) no Python ao assinar sequências?


264

Eu sei que posso usar algo como string[3:4]para obter uma substring em Python, mas o que significam os 3 somesequence[::3]?


o que significa quem vem antes : como [5::]. Então, o que significa 5?
Umar Asghar

1
[5 ::] significaria começar com o primeiro elemento, nada para o segundo e selecionar o próximo elemento
Gagan

Respostas:


243

significa "nada para o primeiro argumento, nada para o segundo e pule três". Ele recebe cada terceiro item da sequência fatiado. Fatias estendidas é o que você deseja. Novo no Python 2.3


99
Ele também pode ser usado para inverter uma lista utilizando [:: - 1]
thavan

22
Ele retorna todos os itens em uma posição com múltiplo de 3 . Como 3 * 0 = 0, ele também retorna o item na posição 0. Por exemplo: range(10)[::3]outputs[0, 3, 6, 9]
Ricky Robinson

1
o que significa quem vem antes ::como [n ::]. Então, o que isso significa n?
Umar Asghar

154

Os endereços de fatia de sequência Python podem ser escritos como um [start: end: step] e qualquer um dos start, stop ou end pode ser eliminado. a[::3]é todo terceiro elemento da sequência.


85

seq[::n] é uma sequência de cada n item-ésimo em toda a sequência.

Exemplo:

>>> range(10)[::2]
[0, 2, 4, 6, 8]

A sintaxe é:

seq[start:end:step]

Então você pode fazer:

>>> range(100)[5:18:2]
[5, 7, 9, 11, 13, 15, 17]

4
No Python 3, seu exemplo de intervalo (N) [:: step] produz um objeto de intervalo, não uma lista. Para realmente ver o que está acontecendo, você precisa coagir o intervalo a uma lista, matriz np. Etc.
PikalaxALT

57

Explicação

s[i:j:k]é, de acordo com a documentação , "fatia de s de i até j com a etapa k". Quando ie jausente, toda a sequência é assumida e, portanto,s[::k] significa "todo k-ésimo item".

Exemplos

Primeiro, vamos inicializar uma lista:

>>> s = range(20)
>>> s
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

Vamos pegar cada terceiro item de s:

>>> s[::3]
[0, 3, 6, 9, 12, 15, 18]

Vamos pegar cada terceiro item de s[2:]:

>>> s[2:]
[2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> s[2::3]
[2, 5, 8, 11, 14, 17]

Vamos pegar cada terceiro item de s[5:12]:

>>> s[5:12]
[5, 6, 7, 8, 9, 10, 11]
>>> s[5:12:3]
[5, 8, 11]

Vamos pegar cada terceiro item de s[:10]:

>>> s[:10]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> s[:10:3]
[0, 3, 6, 9]

resposta incrível!
Jürgen K.

30

TL; DR

Este exemplo visual mostra como selecionar elementos em uma matriz NumPy (matriz bidimensional) de uma maneira bem divertida (prometo). O passo 2 abaixo ilustra o uso desses "dois pontos duplos" ::em questão.

(Cuidado: este é um exemplo específico de array NumPy com o objetivo de ilustrar o caso de uso de "dois-pontos duplos" ::para saltar elementos em vários eixos. Este exemplo não cobre estruturas de dados Python nativas comoList ).

Um exemplo concreto para governar todos eles ...

Digamos que temos uma matriz NumPy que se parece com isso:

In [1]: import numpy as np

In [2]: X = np.arange(100).reshape(10,10)

In [3]: X
Out[3]:
array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
       [20, 21, 22, 23, 24, 25, 26, 27, 28, 29],
       [30, 31, 32, 33, 34, 35, 36, 37, 38, 39],
       [40, 41, 42, 43, 44, 45, 46, 47, 48, 49],
       [50, 51, 52, 53, 54, 55, 56, 57, 58, 59],
       [60, 61, 62, 63, 64, 65, 66, 67, 68, 69],
       [70, 71, 72, 73, 74, 75, 76, 77, 78, 79],
       [80, 81, 82, 83, 84, 85, 86, 87, 88, 89],
       [90, 91, 92, 93, 94, 95, 96, 97, 98, 99]])

Digamos, por algum motivo, que seu chefe deseja que você selecione os seguintes elementos:

insira a descrição da imagem aqui

"Mas como ???" ... Continue lendo! (Podemos fazer isso em uma abordagem em duas etapas)

Etapa 1 - Obter subconjunto

Especifique o "índice inicial" e o "índice final" nas direções de linha e coluna.

insira a descrição da imagem aqui

Em código:

In [5]: X2 = X[2:9,3:8]

In [6]: X2
Out[6]:
array([[23, 24, 25, 26, 27],
       [33, 34, 35, 36, 37],
       [43, 44, 45, 46, 47],
       [53, 54, 55, 56, 57],
       [63, 64, 65, 66, 67],
       [73, 74, 75, 76, 77],
       [83, 84, 85, 86, 87]])

Observe agora que acabamos de obter nosso subconjunto, com o uso de uma técnica simples de indexação de início e fim. A seguir, como fazer isso "pular" ... (leia!)

Etapa 2 - Selecionar elementos (com o argumento "jump step")

Agora podemos especificar as "etapas de salto" nas direções de linha e coluna (para selecionar elementos de maneira "de salto") como este:

insira a descrição da imagem aqui

No código (observe os dois pontos duplos):

In [7]: X3 = X2[::3, ::2]

In [8]: X3
Out[8]:
array([[23, 25, 27],
       [53, 55, 57],
       [83, 85, 87]])

Acabamos de selecionar todos os elementos, conforme necessário! :)

 Consolidar a Etapa 1 (início e fim) e a Etapa 2 ("salto")

Agora que conhecemos o conceito, podemos facilmente combinar as etapas 1 e 2 em uma etapa consolidada - para compacidade:

In [9]: X4 = X[2:9,3:8][::3,::2]

    In [10]: X4
    Out[10]:
    array([[23, 25, 27],
           [53, 55, 57],
           [83, 85, 87]])

Feito!


E se eu quiser definir cada uma dessas entradas marcadas como 0 no objeto original? Como proceder?
precisa saber é o seguinte

1
Faça um X[2:9,3:8][::3,::2] = 0 (para substituir as entradas marcadas para 0). Se você digitar Xnovamente, verá que todas as entradas marcadas estão definidas como 0.
usar o seguinte código

15

Ao fatiar em Python, o terceiro parâmetro é a etapa. Como outros mencionados, consulte Fatias estendidas para uma boa visão geral.

Com esse conhecimento, [::3]significa apenas que você não especificou nenhum índice inicial ou final para sua fatia. Como você especificou uma etapa, 3isso levará a cada terceira entrada, a somethingpartir do primeiro índice. Por exemplo:

>>> '123123123'[::3]
'111'

7

Você também pode usar essa notação em suas próprias classes personalizadas para fazer o que quiser

class C(object):
    def __getitem__(self, k):
        return k

# Single argument is passed directly.
assert C()[0] == 0

# Multiple indices generate a tuple.
assert C()[0, 1] == (0, 1)

# Slice notation generates a slice object.
assert C()[1:2:3] == slice(1, 2, 3)

# If you omit any part of the slice notation, it becomes None.
assert C()[:] == slice(None, None, None)
assert C()[::] == slice(None, None, None)
assert C()[1::] == slice(1, None, None)
assert C()[:2:] == slice(None, 2, None)
assert C()[::3] == slice(None, None, 3)

# Tuple with a slice object:
assert C()[:, 1] == (slice(None, None, None), 1)

# Ellipsis class object.
assert C()[...] == Ellipsis

Podemos então abrir objetos de fatia como:

s = slice(1, 2, 3)
assert s.start == 1
assert s.stop == 2
assert s.step == 3

Isso é usado principalmente no Numpy para cortar matrizes multidimensionais em qualquer direção.

Obviamente, qualquer API sã deve ser usada ::3com a semântica "a cada 3" usual.

O relacionado Ellipsisé abordado mais detalhadamente em: O que o objeto Elipse faz?


6

O terceiro parâmetro é a etapa. Então [:: 3] retornaria todo terceiro elemento da lista / string.


4

O Python usa o :: para separar o valor End, Start e Step.


1
Isso não fornece detalhes suficientes para realmente ser útil.
bstpierre

4
Você não quer dizer "o começo, o fim e o passo"? Parece enganoso listá-los fora de ordem.
Jon Coombs
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.