Numpy: ndarray debe derivar de collections.abc.Sequence?

Creado en 1 dic. 2012  ·  49Comentarios  ·  Fuente: numpy/numpy

@juliantaylor planteó esto en un problema de pandas.

El ejemplo del ticket:

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

Esto ocurre en 3.3 con 1.7.0rc1.dev-3a52aa0 y en 3.2 con 1.6.2.
2.7, por supuesto, no se ve afectado.

El código relacionado 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).")

No pude grep otra ubicación en el stdlib con una prueba similar, pero lib2to3
mostró una equivalencia asumida:

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

en 2,7

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

pero en 3.3 / 3.2

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

Comentario más útil

Sí, simplemente agregue Sequence.register(np.ndarray) algún lugar.

Todos 49 comentarios

Python 3.x simplemente realiza una verificación más estricta en random.sample que Python 2.x. En 2.x, numpy tampoco es una subclase de secuencia (ndarray no tiene métodos index , count o __reversed__ ). Así que creo que puede considerar esto como un mal uso de random.sample o una ruptura de compatibilidad con versiones anteriores de Python 3.x.

Bastante justo, pero dicho esto, podríamos fácilmente _hacer_ ndarray una Secuencia,
ya que todos esos métodos tienen sentido y serían sencillos de
implementar. De hecho, basta con heredarlo, ya que Sequence
proporciona todos los métodos que faltan como mixins.
El 2 de diciembre de 2012 a las 13:30, "Ralf Gommers" [email protected] escribió:

Python 3.x simplemente realiza una verificación más estricta en random.sample que
Python 2.x. En 2.x, numpy tampoco es una subclase de secuencia (ndarray no tiene
índice, recuento o métodos inversos ). Entonces creo que puedes considerar esto como
ya sea un mal uso de random.sample o una ruptura de compatibilidad con versiones anteriores por
Python 3.x.

-
Responda a este correo electrónico directamente o véalo en Gi

Habría dicho lo mismo, si no fuera por el ejemplo 2to3 que lo hace más sutil.
el índice y el recuento no son necesarios, creo: Enlace ,
Todos los métodos abstractos para Sequence ya están implementados. Los demás tienen implementaciones predeterminadas.

El problema es que MutableSequence es más correcto y insert no está implementado.

Sin embargo, no olvide las matrices 0-d, no estoy seguro de lo que sucede con ellas en este momento, pero no son realmente una secuencia, ¿verdad?

Hmm, Sequence está destinado a objetos inmutables, algunos de los métodos de MutableSequence (extender, hacer estallar) no tienen sentido. Entonces sí, podríamos agregar esos 3 métodos, pero no se siente del todo bien.

Me parece que realmente no hay razón para que random.sample requiera una instancia Sequence .

__setitem__ está implementado, pero no __delitem__ , entonces tal vez SomewhatMutableSequence ?

Tiene sentido que interprete la interfaz como "una secuencia debe tener todos estos, pero algunos
have terrible O () ", por lo que ofrecen implementaciones ingenuas de algunos métodos.
Seguramente no es la semántica de insert , pop que no está claro en el contexto de un ndarray.
Sin embargo, no estoy seguro de qué es lo correcto con respecto a la iteración sobre una matriz 0-d.
Se podría argumentar que ofrecer un método __iter__ que solo genera TypeError lugar de
StopIteration es una violación de la escritura pato de todos modos.

editar : Aunque estoy seguro de que no fue una decisión descuidada.

ndarray podría ser simplemente una secuencia, eso no significa que deba ser inmutable.

Por cierto. la implementación de la lista CPython tampoco admite la inserción, extracción y extensión eficientes, pero sigue siendo una secuencia Mutable

ndarray no puede admitir insert / pop / extend en el lugar (los ndarray tienen un tamaño fijo), por lo que si bien es una secuencia mutable, simplemente no es un Python MutableSequence (y nunca lo será). Sin embargo, puede y debe admitir la interfaz Sequence .

Sería bueno si random.sample no marcara esto, pero en una mirada más cercana, tiene una razón plausible: tiene una serie de implementaciones diferentes para diferentes tipos de argumentos de entrada, por lo que necesita alguna forma para distinguir entre ellos. No puede simplemente comenzar a indexar y esperar lo mejor. Tal vez podríamos presentar un error e intentar convencerlos de que recurran a la implementación de la secuencia de forma predeterminada para los tipos no reconocidos, pero lo primero que podría ayudar es 3.4 ...

Sin embargo, el punto sobre las matrices 0-d es bueno; Las matrices 0-d no admiten la interfaz Sequence (ni siquiera son Iterable ). Pero para los propósitos de Python, no es demasiado terrible si mienten acerca de ser Sequence sy luego esperan que el acceso real genere un error: escribir pato significa que siempre puede fallar si lo desea :-). Probablemente sea posible de alguna manera hacer que isinstance(a, Sequence) tenga éxito para matrices multidimensionales y falle para matrices 0-d; si podemos hacer que eso suceda, entonces genial. Pero incluso si no podemos, lo mejor que podemos hacer es probablemente convertir ndarray's en Sequence s.

Tenga en cuenta que MaskedArray ya tiene un método count , por lo que agregar uno en ndarray que haga algo diferente lo romperá.

Los arreglos 0-D se consideran mejor como escalares con algunos métodos útiles (al menos así es como yo los veo); además de no ser iterables, tampoco son indexables, lo que es aún más extraño si los considera como matrices. Entonces, hacer que las matrices 0-D sean inconsistentes de otra manera no es un gran problema en mi humilde opinión.

@njsmith ¿dónde ves múltiples implementaciones? Después de la verificación de isinstance (Sequence), solo veo len(population) y luego una conversión a una lista. http://hg.python.org/cpython/file/22d891a2d533/Lib/random.py

Los tipos Pandas Series y DataFrame también tienen métodos de recuento incompatibles y un atributo de índice.

@rgommers : Hmm, tienes razón, me engañó el mensaje de error y pensé que también aceptaba enteros como abreviatura de range() , lo cual no es así. Aun así, quieren definir comportamientos diferentes para conjuntos, secuencias y asignaciones. Tal vez podamos convencerlos de que deberían cambiarlo a

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

Ese también es un buen punto sobre las subclases ndarray existentes. No parece que haya ninguna forma de decir que ndarray es un Sequence pero sus subclases no son :-(. Entonces, ¿qué opción es menos mala, dado que algunas de estas subclases no pueden satisfacer el Sequence interfaz sin romper la compatibilidad?

  • Desaproveche los usos incompatibles en las subclases de ndarray y, finalmente, elimínelos y reemplácelos con versiones compatibles con Sequence . Esto parece factible para los métodos count , pero cambiar el nombre de Series.index sería muy perjudicial para la gente de los pandas. (DataFrame no es una subclase de ndarray, por lo que técnicamente no es relevante, excepto que supongo que la serie y el DataFrame deben mantenerse sincronizados). Supongo que podemos preguntarle a @wesm qué piensa, pero ...
  • Continúe y declare ndarray y sus subclases para satisfacer la definición Sequence , y acepte que para algunas subclases de ndarray esto será una mentira. Sin embargo, solo en las partes raramente utilizadas de la interfaz Sequence , y los tipos de Python suelen ser mentiras de todos modos ...
  • Re-jigger nuestra jerarquía de herencia para separar la funcionalidad y las tonterías de la clase base abstracta. Hacer
class multidim_ndarray(ndarray, Sequence):
  pass

y, en su lugar, cree instancias de matrices multi-dim de esta clase. Las subclases no se ven afectadas porque continúan heredando de ndarray , no de multidim_ndarray . Por supuesto, un solo objeto ndarray puede hacer la transición entre 0-d y multidimensional a través de .resize() ...

  • Acepte que ndarray nunca será un Sequence .

[La cosa de isSequenceType es un poco distraída. Esa es una función antigua que es anterior a la existencia de clases base abstractas (que se agregaron en 2.6), y ni siquiera intenta precisar la interfaz detallada requerida de las secuencias; solo verifica que su tipo (1) define un __getitem__ , (2) no es un dict incorporado. Obviamente, esto dará una respuesta incorrecta en muchas situaciones (por ejemplo, cualquier cosa que actúe como un dict pero no lo sea). Entonces, si uno realmente quiere un tipo de secuencia, entonces isinstance(obj, Sequence) hará un mejor trabajo y 2to3 está haciendo lo correcto. Pero crea un problema para numpy ...]

Tal vez sería posible convencer a la gente de Python de crear una nueva clase como SequenceBase que esté incluso por debajo de Sequence y no garantice .index o .count , pero solo .__len__ y __getitem__ o tal? Está muy bien que Sequence tenga algo como index , pero parece un poco extraño forzarlo en cosas como numpy aparentemente haciendo que las secuencias como las cosas deberían escribirse con pato. ¿La gente de Python es consciente de que esto es algo problemático?

Me gusta la propuesta de @seberg; si los desarrolladores de Python no están de acuerdo, iría por la segunda viñeta de @njsmith. La opción que falta es simplemente decir que los ndarrays no satisfacen la interfaz de secuencia. No es óptimo, pero mejor que las viñetas 1 y 3 en mi humilde opinión.

[Vaya, la "opción faltante" estaba allí como la opción 4, solo que de alguna manera el analizador de rebajas decidió doblarla en la viñeta anterior de una manera confusa e ilegible. Edité el comentario para corregir el formato.]

La mitad de los tipos que están registrados con Sequence , es decir, buffer y xrange , tampoco tienen estos métodos. No me queda claro que estos sean métodos obligatorios de la interfaz tanto como métodos de conveniencia para aquellos que están usando collections.Sequence como clase base / mixin.

@rkern : Buen partido. Entonces, tal vez la solución sea simplemente agregar una llamada a Sequence.register(np.ndarray) algún lugar. (Esto también sería una solución para el reportero original).

Probablemente deberíamos implementar __reversed__ en algún momento también ...

@rkern , tiene razón, esto se menciona como un tema abierto en el PEP: http://www.python.org/dev/peps/pep-3119/#sequences. Es extraño que los PEP con estado Final puedan incluso tener problemas abiertos.

Creo que el título de este error es un poco engañoso, ya que el error no existe solo en python3. Claro, random.sample(numpy_array) funciona en python2, pero isinstance(np.array([1]), collections.Sequence) debería devolver True en cualquier python> = 2.6.

Acabo de encontrar este error en Python 2.7 usando el módulo autopep8. De forma predeterminada, convirtió algunas de las llamadas operator.isSequenceType () en isinstance (x, collections.Sequence). La prueba se volvería Falsa cuando pase un numpy.ndarray. Esto puede ser un error muy furtivo.

También lo encontré con Python 2.7, usando el módulo python-pillow. Image.point (lut, mode) llama a isinstance (lut, collections.Sequence), la versión anterior utilizada operator.isSequenceType ()

Ahora podría ser un buen momento para revisar esto ya que se registraron los numerosos tipos escalares numéricos (# 4547),

Entonces, tal vez la solución sea simplemente agregar una llamada a Sequence.register (np.ndarray) en algún lugar.

Sí, ese es un buen compromiso.

Sí, simplemente agregue Sequence.register(np.ndarray) algún lugar.

@mitar ¿ algún interés en enviar un PR?

Por supuesto. ¿A dónde debería ir esto? ¿En el mismo archivo donde se crea np.ndarray ?

Solo para estar seguros de que realmente pensamos que esto es una buena idea: ahora estamos agregando una desaprobación para una matriz vacía que es False (# 9718), es decir, estamos eliminando una de las cosas que funcionan para las secuencias) . Aunque al leer los comentarios, creo que la conclusión ya fue que los escalares de matriz no funcionarán, así que supongo que una matriz vacía puede ser parte de esa promesa rota ...

Para referencia futura, el lugar adecuado para hacer esto probablemente sea en numpy.core.multiarray :
https://github.com/numpy/numpy/blob/4f1541e1cb68beb3049a21cbdec6e3d30c2afbbb/numpy/core/multiarray.py

OK, quiero esto. ¿Cómo? Así sería como los implementaría 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)

Descubrimos que con la última versión de Tensorflow (2.0), tener Sequence.register(np.ndarray) hace que Tensorflow se comporte mal. Parece que está verificando en alguna parte si el valor es una secuencia y luego usa es diferente que si es un ndarray.

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

Divertidísimo. Estoy bastante seguro de que probar si algo es una matriz es la mejor idea, porque casi siempre será el caso especialmente manejado.

Probablemente el orden de las comprobaciones de tipo sea incorrecto, primero debería comprobar si hay ndarray y luego la secuencia. Pero si primero verifica la secuencia, ahora se ejecuta ese bloque de código.

@mitar Estamos considerando cerrar esto porque __contains__ / operator.in comporta

¿Puede ampliar el contrato de API que tiene en mente aquí? No lo entiendo exactamente.

El caso de uso es escribir código genérico que sepa cómo convertir entre cosas, como si pudieras iterar sobre una secuencia y recuperar dimensión por diensión, y luego recurrir. Entonces puedo convertir la lista de listas de la misma manera que un ndarray 2d, pero se puede generalizar a múltiples dimensiones, etc. Y no tengo que comprobar más que solo que es una secuencia.

Como se mencionó, hay un par de problemas al ver las matrices como secuencias de Python anidadas. __contains__ es el más obvio, el otro es que los arreglos 0-D definitivamente no son secuencias anidadas. También existen sutilezas, como una dimensión de longitud 0, y generalmente arr[0] = 0 no significa que arr[0] == 0 , ya que arr[0] puede ser una matriz arbitraria en sí misma (que se escribiría mejor como arr[0, ...] . Personalmente, creo que la interpretación de la "secuencia anidada" es agradable, pero menos útil de lo que tendemos a pensar. (Es decir, rara vez repito una matriz como for col in array e incluso si lo hago, no me importaría escribir for col in array.iter(axis=0)

De modo que tiendo a ver la "matriz es una secuencia" como una analogía ligeramente problemática (lo que no significa que no pueda ser útil, lo admito).
Sin embargo, sea cual sea el caso de uso, tengo curiosidad por saber si no sería mejor explorar un nuevo ABC, como un nuevo "ElementwiseContainer". Uno que también le dice al usuario que + y == , etc. funcionarán en cada elemento y que, a diferencia de las secuencias de Python, no deben esperar que + concatenen ( sí + no es parte de la secuencia ABC, pero se siente natural en Python).

Solo pasando por
Escribí a Python-ideas la semana pasada porque noté que collections.abc.Sequence Python no implementa __eq__ y otras comparaciones, a pesar de que tiene todos los otros métodos para implementarlos para que Sequence se comporte como listas y tuplas. (ese hilo de correo me llevó a este problema).

Estaba proponiendo agregar __eq__ allí, pero obviamente haría que esas secuencias divergieran del comportamiento que tiene Numpy.array.

¿Qué hay de formalizar más, en Python, qué son las "Secuencias" y luego delegar estas cosas que divergirían como casos especializados, hasta el punto de agregar un collections.abc.ComparableSequence allí? (y dado que + para cancatenation se mencionó anteriormente, tal vez algún otro nombre que implique "secuencias cuya comparación resulte en un solo bool, y se comporten como escalares para la concatenación y multiplicar por escalar", es decir, el comportamiento de Python para los + y * en lista y tuplas). Por lo tanto, las especificaciones de Sequence podrían formalizarse de tal manera que al menos las matrices numéricas 1D coincidieran exactamente con ellas.

Esta formalización sobre lo que es una secuencia de Python también podría ayudar con otras divergencias, como la mencionada en https://github.com/numpy/numpy/issues/2776#issuecomment -330865166 arriba.

Sin embargo, no me siento lo suficientemente motivado para seguir ese camino solo, pero si esto tiene sentido, felizmente ayudaría a escribir un PEP y ayudaría a impulsarlo. (Solo quería verificar por qué la secuencia no creó un __eq__ , y posiblemente tenga un PR para eso cuando mencioné esto)

@jsbueno, mi problema es que realmente no veo qué definición adicional o intermedia sería realmente útil para los usuarios de ndarray . Lo mejor que se me ocurre es un Collection que tiene count() y index() , pero ¿es útil? Cualquier otra cosa sería un ABC para las cosas de las que Python tiene poco o ningún concepto.

Creo que SymPy lo hizo más bien. Repite todos los elementos de sus matrices, lo que al menos lo convierte en Collection .
Ahora, dudo que podamos hacer mucho al respecto, y ni siquiera estoy seguro de que la iteración SymPy de todos los elementos sea súper útil (e intuitiva), pero al menos la iteración de todos los elementos es consistente con __contains__ . Tenga en cuenta que esto también significa que len(Matrix) es el número de elementos, y _not_ Matrix.shape[0] !

Con el riesgo de repetir mucho desde arriba, además de las matrices 1-D, ¿qué son las matrices numpy ?:

  • Container : de elementos: heavy_check_mark:
  • Sized + Iterable de submatrices (si no es 1-D): pregunta:
  • Reversible : podríamos implementar eso, no se preocupe. :pregunta:
  • count() y index() : se pueden implementar para elementos (: heavy_check_mark :)
  • Sequence : Falta de coincidencia entre el subarreglo iterable y el contenedor de elementos : x:

Entonces, incluso algunas de las propiedades más fundamentales chocan. NumPy podría ser un Container que sepa cómo hacer .index() y .count() , es decir, un Sequence pero sin la parte Iterable . Si bien es independientemente un Iterable , pero de subarreglos .
Y si eso parece un lío confuso, entonces estoy de acuerdo, pero creo que es por diseño. La única solución verdadera sería ir por la ruta SymPy o simplemente no ser un Iterable para empezar. (No podemos seguir la ruta de SymPy, y dudo que desaprobar __iter__ tenga alguna posibilidad).

Personalmente, mi expectativa es que las matrices 1-D a un lado, los me gusta de matrices son simplemente bestias muy diferentes en comparación con las colecciones de Python. Al considerar el comportamiento de la iteración, necesitaría MultidimensionalCollection para señalar específicamente la falta de coincidencia entre __contains__ y __iter__ (pero, ¿es útil?).

Al mirar más allá de lo que está definido actualmente por Sequence , reafirmaré que creo que ElementwiseCollection (los operadores son operadores de elementos en lugar de operadores de contenedores, por ejemplo, + ) es el característica definitoria de matrices numpy y todos los me gusta de matrices en general (ver programación de matrices). Sin embargo, también es un concepto completamente ajeno a Python, y a veces en desacuerdo con él.

Lo único sería marcar matrices unidimensionales, y sólo matrices unidimensionales como secuencias, ya que no tienen el desajuste de subarreglo vs. elemento. En ese momento, sí, __eq__ por supuesto, no está definido para ellos, y __nonzero__ no está definido de forma similar a las secuencias típicas de Python.

Gracias por la respuesta, y me disculpo nuevamente por subirme al vagón de 8 años aquí. Con su comentario, un par de horas después del último intercambio de correo electrónico y charlando con otro amigo en el medio, estoy de acuerdo en que la mayoría de estas cosas es mejor dejarlas como están. En algún momento en el futuro, Python puede optar por tener una definición más formal de Sequence que "cualquier colección.abc.Sequence que implemente ahora".

Solo agregaré, después de leer sus comentarios anteriores, que creo que las características que enumeró como "lo que hace una secuencia de Python" carecen de la característica más importante que hace que los ndarrays se parezcan a secuencias como listas y tuplas para mí: tener un índice contiguo- espacio que puede abordar todos los elementos individuales. Pero no creo que formalizar un abc para eso tenga ningún valor práctico, ya sea en la codificación o en las sugerencias de tipo estático.

@seberg Esa es una gran sinopsis.

Este problema parece estar relacionado con el uso de ndarray en contextos que esperan Sequence o Iterable o Container . Un enfoque simple sería tener miembros en ndarray que expongan vistas baratas que prometan y proporcionen la interfaz adecuada y respondan a los cheques de isinstance . Por ejemplo:

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.

En lugar de que ndarray prometa ser todo para todos, el usuario pregunta lo que necesita, y si ndarray puede proporcionarlo, lo hace de la manera más barata posible. Si no puede, genera una excepción. Esto simplifica el código de usuario moviendo la verificación ndim el usuario debería estar haciendo (especialmente cuando se usan anotaciones de tipo) a ndarray .

¿La última anotación debería ser Sequence y no Iterable ?

@ eric-wieser ¡Sí! Gracias. ¿Cuáles son tus pensamientos?

Bueno, as_subarray_sequence es prácticamente list(arr) :)

@ eric-wieser Sí, pensé que sería más barato proporcionar una vista, pero no tengo ni idea.

Bueno, list(arr) solo produce len(arr) vistas, que terminaría produciendo de todos modos si iterara.

Sigo pensando que nos estamos enfocando demasiado en lo que se puede hacer y no lo suficiente en cuáles son los problemas en este momento. En particular, todos los métodos que proporcionaste anteriormente son muy fáciles de implementar si sabes que tienes un tipo ndarray (no estoy de acuerdo con que las matrices 0-D no son contenedores). Por lo tanto, solo serían útiles si hubiera un ABC estandarizado para ellos, y en ese caso también sería suficiente definir que la indexación básica es muy compatible y tal vez incluya la propiedad .flat .

El problema original ( random.sample dejó de funcionar) parece bastante irrelevante debido al tiempo transcurrido. Sí, es un poco molesto, pero posiblemente sea incluso para mejor, ya que el usuario puede esperar que se elijan los subarreglos o los elementos.

Estoy seguro de que se rompen algún código de pato a escribir. Es probable que ocurran algunos problemas con la serialización (no tengo ejemplos a mano). Y muchos de estos códigos no tendrán ningún problema con el uso de isinstance controles en ABC s, pero odio buscar np.ndarray específicamente. No veo cómo agregar métodos a ndarray ayudaría con eso, necesitaríamos un nuevo ABC , probablemente con poco más que la propiedad .ndim y posiblemente consagrando la iteración de estilo de secuencia anidada.

Métodos como el anterior pueden ser razonables como protocolo de consumidor para trabajar con cualquier arreglo similar, pero ¿es ese el problema que estamos tratando de resolver :)? Parece que no son cosas que las típicas secuencias de Python querrían exponer.

@ eric-wieser

Por supuesto que tiene razón, pero no puede repetir toda la secuencia. Es posible que solo seleccione algunos elementos.

@seberg

Sigo pensando que nos estamos enfocando demasiado en lo que se puede hacer y no lo suficiente en cuáles son los problemas en este momento.

Estoy de acuerdo contigo. ¿Qué tipo de problemas estás imaginando? Me imagino que cuando numpy 1.10 sale con tipos, a veces querré usar una matriz numpy unidimensional como secuencia. Si quiero hacer eso actualmente, necesito:

  • compruebe que sea unidimensional y
  • llame a cast para decirle a mypy que en realidad es una secuencia.

Es por eso que quiero proporcionar un método para hacerlo automáticamente. También odio las interfaces grandes, pero me parece que este tipo de métodos o funciones básicas van a ser cada vez más frecuentes a medida que las anotaciones de tipo se pongan de moda. ¿Qué piensas?

(No estoy de acuerdo con que las matrices 0-D no sean contenedores).

No tengo idea, pero actualmente está recaudando __len__ para estos, por lo que parece que no funcionan como contenedores. Creo que sería útil para mypy informar un error si pasa una matriz 0-D a una función que acepta un contenedor. No se detectará si crea contenedores de matrices 0-D.

necesitaríamos un nuevo ABC, probablemente con poco más que la propiedad .ndim y posiblemente consagrando la iteración de estilo de secuencia anidada.

No quería agregar eso a mi sugerencia, pero creo que ahí es donde te diriges de todos modos. Soy un ávido usuario de la biblioteca JAX maravillosamente diseñada. Me imagino que en el futuro, numpy.ndarray y jax.numpy.ndarray (que tiene subclases) heredarán de algún NDArray abstracto de algún tipo. Podría tener mucho más de ndim . Idealmente, sería NDArray(Generic[T]) al menos, y tal vez el evento también tenga la forma o el número de dimensiones. Podría tener __eq__ devolviendo NDArray[np.bool_] . Probablemente lo sepas mejor que yo :)

Hace unos años, busqué este problema para sugerir que numpy.array debería heredar de collections.Sequence , pero ahora encuentro los argumentos (¡especialmente los tuyos!) En este hilo muy convincentes. Las matrices numpy no son realmente secuencias, y herrarlas parece causar más daño que bien. ¿Por qué no dejar que sean lo suyo y obligar a los usuarios a solicitar explícitamente la interfaz que desean?

Y muchos de esos códigos no tendrán problemas con el uso de verificaciones de isinstance en ABC,

Ahora que mencionas eso, tal vez todos mis métodos propuestos deberían haber devuelto vistas. De esa manera, pueden responder correctamente a las verificaciones de instancias.

Métodos como el anterior pueden ser razonables como protocolo de consumidor para trabajar con cualquier arreglo similar, pero ¿es ese el problema que estamos tratando de resolver :)? Parece que no son cosas que las típicas secuencias de Python querrían exponer.

Definitivamente estoy de acuerdo en que la respuesta a esto depende de los problemas que estemos tratando de resolver. Habiendo bebido el kool aid de anotación de tipo, estoy interesado en escribir un código numpy sucinto que pase mypy sin ensuciar el código con # type: ignore . ¿Qué problemas tienes en mente?

Bueno, las sugerencias de tipo y la interoperabilidad con otros objetos similares a matrices son probablemente una buena motivación. Podría sugerir abrir un tema nuevo o un hilo de lista de correo. En este momento, no estoy seguro de qué es lo mejor para pensar aquí, mecanografiar se está formando, así que tal vez eso termine aclarando algunas cosas.

¿Fue útil esta página
0 / 5 - 0 calificaciones