Como você usa a sintaxe de corte de reticências no Python?

Respostas:

102

Ellipsis, ou ...não é um recurso oculto, é apenas uma constante. É bem diferente, digamos, do javascript ES6, onde faz parte da sintaxe da linguagem. Nenhuma classe incorporada ou constituição de linguagem Python faz uso dela.

Portanto, a sintaxe depende inteiramente de você, ou de alguém, ter escrito um código para entendê-lo.

O Numpy usa-o, conforme indicado na documentação . Alguns exemplos aqui .

Na sua própria classe, você usaria assim:

>>> class TestEllipsis(object):
...     def __getitem__(self, item):
...         if item is Ellipsis:
...             return "Returning all items"
...         else:
...             return "return %r items" % item
... 
>>> x = TestEllipsis()
>>> print x[2]
return 2 items
>>> print x[...]
Returning all items

Obviamente, existe a documentação do python e a referência da linguagem . Mas esses não são muito úteis.

nosklo
fonte
6
parece bastante quebrado desde o caminho "propper" para dizer todos os itens é >>> x [:] >>> x [:, 1: 2]
Ronny
30
@ Ronny: O objetivo era demonstrar um uso personalizado da elipse.
Nosklo 8/05/09
7
Os links parecem estar quebrados.
SwiftsNamesake
231

As reticências são usadas em numpy para cortar estruturas de dados de dimensões mais altas.

Ele foi projetado para significar que , neste ponto, insira tantas fatias completas ( :) para estender a fatia multidimensional a todas as dimensões .

Exemplo :

>>> from numpy import arange
>>> a = arange(16).reshape(2,2,2,2)

Agora, você tem uma matriz quadridimensional da ordem 2x2x2x2. Para selecionar todos os primeiros elementos na quarta dimensão, você pode usar a notação de reticências

>>> a[..., 0].flatten()
array([ 0,  2,  4,  6,  8, 10, 12, 14])

que é equivalente a

>>> a[:,:,:,0].flatten()
array([ 0,  2,  4,  6,  8, 10, 12, 14])

Em suas próprias implementações, você pode ignorar o contrato mencionado acima e usá-lo para o que achar melhor.

Torsten Marek
fonte
Talvez eu esteja errado, mas não é isso que a[:,:,:,0]retornará uma cópia e a[...,0]retornará a "visualização" e não a cópia? Tentei rodar id()com as duas versões e com uma matriz tridimensional: a[:,:,:, 0], a[:,:,:, 1], a[:,:,:, 2] todos têm IDs diferentes, enquanto: a[..., 0], a[..., 1], a[..., 2] todos têm os mesmos IDs.
precisa saber é o seguinte
@ mohitsharma44 não está na minha máquina;) id()retorna o mesmo valor para ambos. Também verificar com __array_interface__['data']mostra o mesmo endereço de memória.
BoltzmannBrain
Acho que podemos usar a[indexes, ...]enquanto a é uma matriz 1-dimensional;
acgtyrant
1
Elipses também são úteis para estruturas de dados de dimensão zero. Eles são a única maneira que eu conheço de escrever em escalpy numpy.ndarrays, por exemplo: my_scalar = np.asarray (3); my_scalar [...] = 5. Se você fizer my_scalar [:] = 5, receberá um erro com razão, porque não há dimensão 0 para o: para iterar.
SuperElectric
1
@SuperElectric Você também pode usar my_scalar.itemset (scalarvalue). Obviamente, my_scalar [...] = scalar_value é mais curto, mas você disse no comentário acima, que é a única maneira que você conhece. Apenas dando uma alternativa.
precisa saber é
70

Esse é outro uso da elipse, que não tem nada a ver com fatias: costumo usá-la na comunicação intra-thread com filas, como uma marca que sinaliza "Concluído"; está lá, é um objeto, é um singleton e seu nome significa "falta de", e não é o None em excesso (que pode ser colocado em uma fila como parte do fluxo de dados normal). YMMV.

tzot
fonte
14
Não seria mais claro apenas dizer: "Concluído = object ()" em algum lugar e apenas usá-lo?
Brandon Rhodes
12
Não necessariamente - exige que você realmente diga Concluído = object () em algum lugar. Os valores do Sentinel não são necessariamente uma coisa ruim - e usar singletons Python quase inúteis como sentinelas não é tão horrível como IMO (reticências e () são as que eu usei onde Nenhum seria confuso).
22410 Rick Copeland
6
Em relação a Concluído = object (), acho que usar reticências é melhor, especialmente se você estiver usando para comunicação com filas. Se você passar da comunicação intra-thread para intra-processo, o ID (Concluído) não será o mesmo no outro processo e não haverá nada para distinguir um objeto do outro. O id da elipse também não será o mesmo, mas pelo menos o tipo será o mesmo - esse é o objetivo de um singleton.
precisa saber é o seguinte
A pergunta diz "Como você usa reticências", mas acredito que você entendeu errado. Tem muitas interpretações. Mas acho que o correto é: "Como a elipse é usada?" ou seja, "Quais etapas devo executar para usar as reticências no meu próprio código.".
Lyndon Branco
6

Conforme indicado em outras respostas, ele pode ser usado para criar fatias. Útil quando você não deseja escrever muitas notações de fatias completas ( :) ou quando não tem certeza sobre qual é a dimensionalidade da matriz que está sendo manipulada.

O que achei importante destacar, e que faltava nas outras respostas, é que ele pode ser usado mesmo quando não há mais dimensões a serem preenchidas.

Exemplo:

>>> from numpy import arange
>>> a = arange(4).reshape(2,2)

Isso resultará em erro:

>>> a[:,0,:]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: too many indices for array

Isso funcionará:

a[...,0,:]
array([0, 1])
Mauricio Perez
fonte