Numpy: ndarray deve derivar de coleções.abc.Sequence?

Criado em 1 dez. 2012  ·  49Comentários  ·  Fonte: numpy/numpy

@juliantaylor levantou isso em uma questão dos pandas.

O exemplo do tíquete:

import numpy as np
import random
random.sample(np.array([1,2,3]),1)

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/user1/py33/lib/python3.3/random.py", line 298, in sample
    raise TypeError("Population must be a sequence or set.  For dicts, use list(d).")
TypeError: Population must be a sequence or set.  For dicts, use list(d).

Isso ocorre em 3.3 com 1.7.0rc1.dev-3a52aa0 e em 3.2 com 1.6.2.
2.7 não é afetado, é claro.

O código relavent de cpython / Lib / random.py: 297

from collections.abc import Set as _Set, Sequence as _Sequence
def sample(self, population, k):
# ...
    if not isinstance(population, _Sequence):
        raise TypeError("Population must be a sequence or set.  For dicts, use list(d).")

Não consegui realizar o grep em outro local no stdlib com um teste semelhante, mas lib2to3
mostrou uma equivalência assumida:

lib2to3/fixes/fix_operator.py
5:operator.isSequenceType(obj)   -> isinstance(obj, collections.Sequence)

em 2,7

In [6]: operator.isSequenceType(np.array([1]))
Out[6]: True

mas em 3.3 / 3.2

>>> isinstance(np.array([1]), collections.Sequence)
False

Comentários muito úteis

Sim, basta adicionar Sequence.register(np.ndarray) algum lugar.

Todos 49 comentários

Python 3.x simplesmente executa uma verificação mais estrita em random.sample que Python 2.x. Em 2.x, numpy também não é uma subclasse de Sequência (ndarray não tem métodos index , count ou __reversed__ ). Portanto, acho que você pode considerar isso como uso incorreto de random.sample ou uma quebra de compatibilidade com versões anteriores do Python 3.x.

É justo, mas dito isso, poderíamos facilmente _fazer_ e traçar uma sequência,
uma vez que todos esses métodos fazem sentido e seriam simples de
implemento. Na verdade, apenas herdar dele já seria o suficiente, já que o Sequence
fornece todos os métodos ausentes como mixins.
Em 2 de dezembro de 2012, às 13:30, "Ralf Gommers" [email protected] escreveu:

Python 3.x simplesmente executa uma verificação mais estrita em random.sample do que
Python 2.x. Em 2.x, numpy também não é uma subclasse de Sequência (ndarray não tem
índice, contagem ou métodos reversos ). Então eu acho que você pode considerar isso como
uso incorreto de random.sample ou quebra de compatibilidade com versões anteriores por
Python 3.x.

-
Responda a este e-mail diretamente ou visualize-o em Gi tHubhttps: //github.com/numpy/numpy/issues/2776#issuecomment -10929601.

Eu teria dito a mesma coisa se não fosse pelo exemplo 2to3 que torna isso mais sutil.
índice e contagem não são necessários, eu acredito: Link ,
Todos os métodos abstratos para Sequence já estão implementados, os outros têm implementações padrão.

O problema é que MutableSequence é realmente mais correto e insert não está implementado.

não se esqueça dos arrays 0-d, não tenho certeza do que acontece com eles agora, mas eles não são realmente uma Sequência, são?

Hmm, Sequence é destinado a objetos imutáveis, alguns dos métodos de MutableSequence (extend, pop) não fazem sentido. Então, sim, poderíamos adicionar esses 3 métodos, mas não parece muito certo.

Parece-me que realmente não há razão para random.sample requerer uma instância Sequence .

__setitem__ está implementado, mas não __delitem__ , então talvez SomewhatMutableSequence ?

Faz sentido interpretar a interface como "uma sequência deve ter tudo isso, mas alguns podem
têm O () "terrível, e é por isso que eles oferecem implementações ingênuas de alguns métodos.
Certamente não é a semântica de insert , pop que não é clara no contexto de um ndarray.
Não tenho certeza de qual é a coisa certa em relação à iteração em uma matriz 0-d, no entanto.
Alguém poderia argumentar que oferecer um método __iter__ que apenas levanta TypeError vez de
StopIteration é uma violação da digitação de pato de qualquer maneira.

editar : Embora eu tenha certeza de que não foi uma decisão descuidada.

ndarray poderia ser apenas uma Sequência, o que não significa que deva ser imutável.

Btw. a implementação da lista de CPython também não suporta inserção, pop e extensão eficientes, mas ainda é uma MutableSequence

ndarray não pode suportar insert / pop / extend no local (ndarray tem um tamanho fixo), então embora seja uma sequência mutável, simplesmente não é um Python MutableSequence (e nunca será). Porém, ele pode e deve oferecer suporte à interface Sequence .

Seria bom se random.sample não verificasse isso, mas olhando mais de perto, tem um motivo plausível - tem várias implementações diferentes para diferentes tipos de argumentos de entrada, então precisa de alguma maneira para distinguir entre eles. Ele não pode simplesmente começar a indexar e esperar o melhor. Talvez pudéssemos registrar um bug e tentar convencê-los a recorrer à implementação da sequência por padrão para tipos não reconhecidos, mas o mais antigo que pode ajudar é 3.4 ...

A questão sobre arrays 0-d é boa, entretanto; Os arrays 0-d não suportam a interface Sequence (eles nem mesmo são Iterable ). Mas para os propósitos do Python, não é tão terrível se eles mentirem sobre ser Sequence s e então esperarem pelo acesso real para gerar um erro - digitação forçada significa que você sempre pode falhar se quiser :-). Provavelmente, é possível fazer com que isinstance(a, Sequence) sucesso para arrays multidimensionais e falhe para arrays 0-d; se pudermos fazer isso acontecer, ótimo. Mas mesmo que não possamos, a melhor coisa a fazer é provavelmente transformar o ndarray em Sequence s.

Observe que MaskedArray já tem um método count , então adicionar um em ndarray que faça algo diferente irá quebrar isso.

Matrizes 0-D são melhor consideradas como escalares com alguns métodos úteis (pelo menos é assim que penso neles); além de não serem iteráveis, eles também não são indexáveis, o que é ainda mais estranho se você pensar neles como arrays. Portanto, tornar os arrays 0-D inconsistentes de outra maneira não é um grande problema para mim.

@njsmith onde você vê várias implementações? Após a verificação isinstance (Sequence), vejo apenas len(population) e, em seguida, uma conversão para uma lista. http://hg.python.org/cpython/file/22d891a2d533/Lib/random.py

Os tipos Pandas Series e DataFrame também têm métodos de contagem incompatíveis e um atributo de índice.

@rgommers : Hmm, você está certo, fui enganado pela mensagem de erro e pensando que ela também aceitava números inteiros como abreviação para range() , o que não acontece. Mesmo assim, eles querem definir comportamentos diferentes para conjuntos, sequências e mapeamentos. Talvez possamos convencê-los de que devem mudar para

if isinstance(population, _Set):
    population = tuple(population)
if isinstance(population, _Mapping):
    raise Blarrrgh()
# Otherwise assume that we have a sequence and hope

Esse também é um bom ponto sobre as subclasses ndarray existentes. Parece que não há como dizer que ndarray é Sequence mas suas subclasses não são :-(. Então, qual opção é a menos ruim, dado que algumas dessas subclasses não podem satisfazer Sequence Interface

  • Descontinue os usos incompatíveis nas subclasses ndarray e, eventualmente, remova-os e substitua-os por versões compatíveis com Sequence . Isso parece factível para os métodos count , mas mudar o nome de Series.index seria extremamente perturbador para o pessoal dos pandas. (DataFrame não é uma subclasse de ndarray, então tecnicamente não é relevante, exceto que eu acho que Series e DataFrame devem ser mantidos em sincronia.) Acho que podemos perguntar a @wesm o que ele pensa, mas ...
  • Vá em frente e declare ndarray e suas subclasses para satisfazer a definição Sequence , e aceite que para algumas subclasses de ndarray isso será uma mentira. Apenas nas partes raramente usadas da interface Sequence , entretanto, e os tipos Python geralmente são mentiras de qualquer maneira ...
  • Refaça nossa hierarquia de herança para separar a funcionalidade e o absurdo da classe base abstrata. Faz
class multidim_ndarray(ndarray, Sequence):
  pass

e, em vez disso, crie instâncias de matrizes multi-dim dessa classe. As subclasses não são afetadas porque continuam a herdar de ndarray , não multidim_ndarray . Claro, um único objeto ndarray pode fazer a transição entre 0-d e multidimensional por meio de .resize() ...

  • Aceite que ndarray nunca será um Sequence .

[A coisa isSequenceType é um pouco uma distração. Essa é uma função antiga que antecede a existência de classes de base abstratas (que foram adicionadas no 2.6), e nem mesmo tenta definir a interface detalhada exigida das sequências - ela apenas verifica se seu tipo (1) define um __getitem__ , (2) não é um dict embutido. Obviamente, isso dará a resposta errada em muitas situações (por exemplo, qualquer coisa que atue como um ditado, mas não o seja!). Então, se alguém realmente quiser um tipo de sequência, isinstance(obj, Sequence) fará um trabalho melhor e 2to3 estará fazendo a coisa certa. Mas isso cria um problema para entorpecido ...]

Talvez fosse possível convencer o pessoal do python a criar uma nova classe como SequenceBase que está ainda abaixo de Sequence e não garante .index ou .count , mas apenas .__len__ e __getitem__ ou algo semelhante? É muito bom que a Sequence tenha algo como index , mas parece um pouco estranho forçá-la em coisas como numpy aparentemente fazendo com que a sequência como as coisas devam ser digitadas como pato. O pessoal do python está ciente de que isso é um tanto problemático?

Gosto da proposta do @seberg; se os desenvolvedores de Python discordarem, eu pegaria o segundo item de @njsmith. A opção ausente é apenas dizer que ndarrays não satisfazem a interface Sequence. Não é ideal, mas é melhor do que os marcadores 1 e 3 imho.

[Opa, a "opção ausente" estava lá como opção 4, mas de alguma forma o analisador de redução decidiu dobrá-la no marcador anterior de uma maneira confusa e ilegível. Editei o comentário para corrigir a formatação.]

Metade dos tipos registrados com Sequence , ou seja, buffer e xrange , também não possuem esses métodos. Não está claro para mim que esses sejam métodos obrigatórios da interface tanto quanto métodos de conveniência para aqueles que estão usando collections.Sequence como uma classe / mixin base.

@rkern : Boa pegada. Então, talvez a solução seja apenas adicionar uma chamada para Sequence.register(np.ndarray) algum lugar. (Isso também seria uma solução alternativa para o relator original.)

Provavelmente deveríamos implementar __reversed__ em algum momento também ...

@rkern, você está certo, isso é mencionado como um problema aberto no PEP: http://www.python.org/dev/peps/pep-3119/#sequences. Estranho que os PEPs com status Final possam até ter questões em aberto.

Acho que o título deste bug é um pouco enganador, pois o bug não existe apenas em python3. Claro, random.sample(numpy_array) funciona em python2, mas isinstance(np.array([1]), collections.Sequence) deve retornar True em qualquer python> = 2.6.

Acabei de encontrar esse bug no Python 2.7 usando o módulo autopep8. Por padrão, ele converteu algumas das chamadas de operator.isSequenceType () em isinstance (x, Collections.Sequence). O teste se tornará falso quando eu passar em um numpy.ndarray. Isso pode ser um bug muito sorrateiro.

Também o encontrei com o Python 2.7, usando o módulo python-pillow. Image.point (lut, mode) chama isinstance (lut, Collections.Sequence), a versão anterior usada operator.isSequenceType ()

Agora pode ser um bom momento para revisitar isso, já que os numerosos tipos escalares numéricos foram registrados (# 4547),

Então, talvez a solução seja apenas adicionar uma chamada para Sequence.register (np.ndarray) em algum lugar.

Sim, é um bom compromisso.

Sim, basta adicionar Sequence.register(np.ndarray) algum lugar.

@mitar algum interesse em enviar um PR?

Certo. Para onde isso vai? No mesmo arquivo onde np.ndarray é criado?

Apenas para ter certeza de que realmente achamos que esta é uma boa ideia: estamos apenas agora adicionando uma depreciação para um array vazio sendo False (# 9718), ou seja, estamos removendo uma das coisas que funcionam para sequências) . Apesar de ler os comentários, acho que a conclusão já foi que os escalares de array não funcionam, então acho que um array vazio pode fazer parte dessa promessa quebrada ...

Para referência futura, o lugar adequado para fazer isso provavelmente seria em numpy.core.multiarray :
https://github.com/numpy/numpy/blob/4f1541e1cb68beb3049a21cbdec6e3d30c2afbbb/numpy/core/multiarray.py

OK, eu quero isso. Quão? Seria assim que eu os implementaria como métodos:

def __reversed__(self):
    return iter(self[::-1])

def index(self, value) -> int:
    return np.in1d(self, value).nonzero()[0]

def count(self, value) -> int:
    return (self == value).sum()

# Necessary due to lack of __subclasshook__
collections.abc.register(np.ndarray)

Descobrimos que com a versão mais recente do Tensorflow (2.0), ter Sequence.register(np.ndarray) faz o Tensorflow se comportar mal. Parece que está verificando em algum lugar se o valor é uma sequência e o usa é diferente do que se for um ndarray.

Veja: https://gitlab.com/datadrivendiscovery/d3m/issues/426

Hilário. Tenho certeza de que testar se algo é um array é a melhor ideia, porque quase sempre será o caso especialmente tratado.

Provavelmente, a ordem das verificações de tipo está errada; primeiro, deve-se verificar o ndarray e depois a sequência. Mas se você primeiro verificar a sequência, agora esse bloco de código será executado.

@mitar Estamos considerando encerrar isso porque __contains__ / operator.in se comporta de maneira diferente (é recorrente e não para sequências), portanto, quebra o contrato de API. Você tem um caso de uso para isso?

Você pode explicar melhor o contrato de API que tem em mente aqui. Eu não entendo exatamente.

O caso de uso é escrever um código genérico que sabe como converter entre coisas, como se você pudesse iterar em uma sequência e recuperar dimensão por diensão e, em seguida, fazer a recursão. Então, posso converter a lista de listas da mesma maneira que um 2º ndarray, mas pode generalizar para várias dimensões e assim por diante. E não preciso verificar mais do que apenas uma sequência.

Conforme mencionado, há alguns problemas em ver arrays como sequências python aninhadas. __contains__ é o mais óbvio, o outro é que os arrays 0-D definitivamente não são sequências aninhadas. Também existem sutilezas, como uma dimensão de comprimento 0, e geralmente arr[0] = 0 não significa que arr[0] == 0 , uma vez que arr[0] pode ser um array arbitrário em si (que seria melhor escrito como arr[0, ...] . Pessoalmente, acho que a interpretação da "sequência aninhada" é boa, mas menos útil do que tendemos a pensar. (Ou seja, raramente itero uma matriz como for col in array e mesmo que o faça, eu não se importaria de escrever for col in array.iter(axis=0)

Portanto, tendo a ver o "array é uma sequência" como uma analogia ligeiramente problemática (o que não significa que não possa ser útil, admito).
No entanto, seja qual for o caso de uso, estou curioso para saber se não seria melhor explorar um novo ABC, como um novo "ElementwiseContainer". Um que também diz ao usuário que + e == , etc. funcionarão em cada elemento , e que, ao contrário das sequências Python, eles não devem esperar que + concatenem ( sim + não faz parte da Sequência ABC, mas parece natural em Python).

Apenas passando -
Escrevi para Python-ideas na semana passada porque notei que collections.abc.Sequence do Python não implementa __eq__ e outras comparações - embora tenha todos os outros métodos para implementar aqueles para fazer Sequence se comportar como listas e tuplas. (esse tópico de correio me levou a esse problema).

Eu estava propondo adicionar __eq__ lá, mas obviamente faria com que essas sequências divergissem do comportamento de Numpy.array.

Que tal formalizar mais, em Python, o que são "Sequências" e então delegar essas coisas que divergem como casos especializados - a ponto de adicionar collections.abc.ComparableSequence lá? (e uma vez que + para cancelamento foi mencionado acima, talvez algum outro nome que implicaria "sequências cuja comparação resulta em um único bool, e se comportam como escalares para concatenação e multiplicam por escalar" - isto é - o comportamento do Python para + e * na lista e tuplas). Portanto, as especificações em Sequence poderiam ser formalizadas de forma que pelo menos 1D numpy arrays corresponderiam exatamente.

Esta formalização sobre o que é uma Sequência Python também pode ajudar com outras divergências, como a mencionada em https://github.com/numpy/numpy/issues/2776#issuecomment -330865166 acima.

No entanto, não estou me sentindo motivado o suficiente para seguir esse caminho sozinho - mas se isso fizer sentido, ficaria feliz em ajudar a escrever um PEP e ajudá-lo a levá-lo adiante. (Eu só queria verificar por que a sequência não criou um __eq__ e, possivelmente, tenho um PR para isso quando mencionei isso)

@jsbueno, meu problema é que eu realmente não vejo qual definição adicional ou intermediária seria realmente útil para usuários de ndarray . O melhor que posso pensar é um Collection que tem count() e index() , mas isso é útil? Qualquer outra coisa seria um ABC para coisas que o próprio Python tem pouco ou nenhum conceito.

Acho que SymPy acertou melhor. Ele itera por todos os elementos de suas matrizes, o que pelo menos o torna um Collection .
Agora, eu duvido que possamos fazer muito sobre isso, e nem mesmo tenho certeza de que a iteração SymPy de todos os elementos seja muito útil (e intuitiva), mas pelo menos a iteração de todos os elementos é consistente com __contains__ . Observe que isso também significa que len(Matrix) é o número de elementos e _not_ Matrix.shape[0] !

Com o risco de repetir muito de cima, além dos arrays 1-D, o que são arrays entorpecidos ?:

  • Container : de elementos: heavy_check_mark:
  • Sized + Iterable de subarrays (se não 1-D): pergunta:
  • Reversible : poderíamos simplesmente implementar isso, não se preocupe. :questão:
  • count() e index() : podem ser implementados para elementos (: heavy_check_mark :)
  • Sequence : Incompatibilidade entre o subarray iterável e o recipiente do elemento : x:

Portanto, mesmo algumas das propriedades mais fundamentais entram em conflito. NumPy poderia ser um Container que sabe como fazer .index() e .count() , ou seja, um Sequence mas sem a parte Iterable . Embora seja independentemente um Iterable , mas de subarrays .
E se isso parece uma bagunça confusa, então eu concordo, mas acho que é intencional. A única solução verdadeira seria ir para o caminho SymPy ou simplesmente não ser Iterable para começar. (não podemos seguir o caminho SymPy e duvido que a suspensão de __iter__ tenha uma chance.)

Pessoalmente, minha expectativa é que os arrays 1-D à parte, os tipos de array são simplesmente feras muito diferentes em comparação com as coleções Python. Ao considerar o comportamento da iteração, você precisaria de MultidimensionalCollection para sinalizar especificamente a incompatibilidade entre __contains__ e __iter__ (mas isso é útil?).

Ao olhar além do que está definido atualmente por Sequence , irei reafirmar que acho que ElementwiseCollection (operadores são operadores de elementos em vez de operadores de contêineres, por exemplo, + ) é o mais definindo características de matrizes numpy e todos os tipos de matrizes em geral (consulte a programação de matrizes). É também um conceito completamente estranho - e às vezes em desacordo com - o próprio Python.

A única coisa seria marcar arrays unidimensionais, e apenas arrays unidimensionais como sequências, uma vez que eles não possuem a incompatibilidade de subarray vs. elemento. Nesse ponto, sim, __eq__ obviamente não está definido para eles, e __nonzero__ não é definido de forma semelhante às sequências python típicas.

Obrigado pela resposta, e peço desculpas novamente por pular no vagão de 8 anos aqui. Com o seu comentário, algumas horas após a última troca de e-mail, e conversando com outro amigo no meio, concordo que é melhor deixar como estão. Em algum momento no futuro, o Python pode optar por ter uma definição mais formal de Sequence do que "qualquer coleção que .abc.Sequence implemente agora".

Vou apenas acrescentar, depois de ler seus comentários acima, que acho que as características que você listou como "o que faz uma sequência Python" carecem do recurso mais importante que faz ndarrays se assemelharem a sequências como listas e tuplas para mim: ter um índice contíguo espaço que pode abranger todos os elementos individuais. Mas não acho que formalizar um abc para isso teria qualquer valor prático, seja na codificação ou na sugestão do tipo estático.

@seberg Essa é uma ótima sinopse.

Este problema parece ser sobre o uso de ndarray em contextos que esperam Sequence ou Iterable ou Container . Uma abordagem simples seria ter membros em ndarray que expõem visualizações baratas que prometem e fornecem a interface apropriada e respondem a cheques de isinstance . Por exemplo:

class ndarray(Generic[T]):
    def as_container(self) -> Container[T]:
        if self.ndim == 0:
            raise ValueError
        return ContainerView(self)  # correctly answers __len__, __iter__ etc.
    def as_subarray_iterable(self) -> Iterable[np.ndarray[T]]:
        if self.ndim <= 1:
            raise ValueError
        return SubarrayIterableView(self)
    def as_scalar_sequence(self) -> Sequence[T]:
        if self.ndim != 1:
            raise ValueError
        return ScalarView(self)
    def as_subarray_sequence(self) -> Sequence[np.ndarray[T]]:
        if self.ndim <= 1:
            raise ValueError
        return SubarraySequenceView(self)  # this view has to reinterpret __contains__ to do the expected thing.

Em vez de ndarray prometer ser tudo para todos, o usuário pergunta o que precisa e, se ndarray puder fornecê-lo, ele o fará da maneira mais barata possível. Se não puder, ele gerará uma exceção. Isso simplifica o código do usuário movendo a verificação ndim o usuário deve fazer (especialmente ao usar anotações de tipo) para ndarray .

Essa última anotação deve ser Sequence e não Iterable ?

@ eric-wieser Sim! Obrigado. Quais são seus pensamentos?

Bem, as_subarray_sequence é praticamente list(arr) :)

@ eric-wieser Sim, pensei que seria mais barato fornecer uma vista, mas não tenho ideia.

Bem, list(arr) apenas produz len(arr) visualizações, que você acabaria produzindo de qualquer maneira se iterasse.

Ainda acho que estamos nos concentrando muito no que pode ser feito e não o suficiente em quais são os problemas neste momento. Em particular, todos os métodos fornecidos acima são muito fáceis de implementar se você souber que tem um ndarray (não concordo que os arrays 0-D não são contêineres). Portanto, eles só seriam úteis se houvesse um ABC padronizado para eles e, nesse caso, também seria suficiente definir que a indexação básica é compatível com numpy e talvez incluir a propriedade .flat .

O problema original ( random.sample parou de funcionar) parece bastante irrelevante devido ao tempo passado. Sim, é um pouco chato, mas possivelmente é para melhor, já que o usuário pode esperar que os subarrays ou os elementos sejam escolhidos.

Estou certo de que não quebrar alguns códigos de pato digitação. Alguns problemas provavelmente ocorrem com a serialização (não tenho exemplos disponíveis). E muitos desses códigos não terão problemas com o uso de isinstance cheques em ABC s, mas odeiam verificar np.ndarray especificamente. Não vejo como adicionar métodos a ndarray ajudaria com isso, precisaríamos de um novo ABC , provavelmente com pouco mais do que a propriedade .ndim e possivelmente consagrando a iteração de estilo de sequência aninhada.

Métodos como os acima podem ser razoáveis ​​como um protocolo de consumidor para funcionar com qualquer tipo de array, mas é esse o problema que estamos tentando resolver :)? Eles não parecem coisas que as sequências típicas do Python gostariam de expor.

@ eric-wieser

Você está certo, é claro, mas não pode iterar em toda a sequência. Você pode escolher apenas alguns elementos.

@seberg

Ainda acho que estamos nos concentrando muito no que pode ser feito e não o suficiente em quais são os problemas neste momento

Eu concordo com você. Que tipo de problemas você está imaginando? Estou imaginando que, quando numpy 1.10 sair com tipos, às vezes vou querer usar uma matriz numpy unidimensional como uma sequência. Se eu quiser fazer isso atualmente, preciso:

  • verifique se é unidimensional e
  • chame cast para dizer a mypy que na verdade é uma sequência.

É por isso que desejo fornecer um método para fazer isso automaticamente. Eu odeio interfaces grandes também, mas me parece que esses tipos de métodos ou funções básicas serão cada vez mais prevalentes à medida que as anotações de tipo se tornarem populares. O que você acha?

(Eu discordo que matrizes 0-D não são contêineres).

Não tenho ideia, mas atualmente você está arrecadando __len__ para eles, então parece que eles não funcionam como contêineres. Acho que seria útil para mypy relatar um erro se você passar um array 0-D para uma função que aceita um contêiner. Ele não pegará se você fizer contêineres de arrays 0-D.

precisaríamos de um novo ABC, provavelmente com pouco mais do que a propriedade .ndim e possivelmente consagrando a iteração de estilo de sequência aninhada.

Eu não queria adicionar isso à minha sugestão, mas acho que é para onde você está indo de qualquer maneira. Sou um usuário ávido da biblioteca JAX maravilhosamente projetada. Eu imagino que, no futuro, numpy.ndarray e jax.numpy.ndarray (que tem subclasses) herdarão de algum tipo NDArray abstrato. Você poderia ter muito mais do que ndim . Idealmente, seria pelo menos NDArray(Generic[T]) e talvez o evento também tivesse a forma ou o número de dimensões. Ele poderia ter __eq__ retornando NDArray[np.bool_] . Você provavelmente sabe melhor do que eu :)

Há alguns anos, pesquisei esse problema para sugerir que numpy.array deveria herdar de collections.Sequence , mas agora acho os argumentos (especialmente os seus !!) neste tópico muito convincentes. Matrizes numpy não são realmente sequências, e calçá-las parece que causará mais mal do que bem. Por que não deixá-los fazer o que querem e forçar os usuários a solicitar explicitamente a interface que desejam?

E muitos desses códigos não terão problemas com o uso de verificações de isinstance em ABCs,

Agora que você mencionou isso, talvez todos os meus métodos propostos devessem ter retornado visualizações. Dessa forma, eles podem responder corretamente a verificações de isinstância.

Métodos como os acima podem ser razoáveis ​​como um protocolo de consumidor para funcionar com qualquer tipo de array, mas é esse o problema que estamos tentando resolver :)? Eles não parecem coisas que as sequências típicas do Python gostariam de expor.

Definitivamente, concordo que a resposta a isso depende dos problemas que estamos tentando resolver. Tendo bebido a anotação de tipo kool aid, estou interessado em escrever um código numpy sucinto que passe mypy sem espalhar o código com # type: ignore . Quais problemas você tem em mente?

Bem, dicas de tipo e interoperabilidade com outros objetos do tipo array são provavelmente uma boa motivação. Eu poderia sugerir a abertura de um novo problema ou tópico da lista de discussão. No momento, não tenho certeza sobre o que pensar melhor aqui, digitação está se formando, então talvez isso acabe esclarecendo algumas coisas.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

Levstyle picture Levstyle  ·  3Comentários

navytux picture navytux  ·  4Comentários

keithbriggs picture keithbriggs  ·  3Comentários

astrofrog picture astrofrog  ·  4Comentários

marcocaccin picture marcocaccin  ·  4Comentários