Pasando nueva forma a `np.reshape`

Dentro de numpy.ndarray.reshape , el parámetro shape es un int o tuple of ints , y

La nueva forma debe ser compatible con la forma original. Si es un entero, entonces el resultado será una matriz 1-D de esa longitud.

La firma de la documentación es sólo:

 # Note this question doesn't apply to the function version, `np.reshape` np.ndarray.reshape(shape, order='C') 

En la práctica, la especificación no parece ser tan estricta. De la descripción anterior esperaría tener que usar:

 import numpy as np a = np.arange(12) b = a.reshape((4,3)) # (4,3) is passed to `newshape` 

Pero en cambio puedo salirme con la suya solo con:

 c = a.reshape(4,3) # Seems like just 4 would be passed to `newshape` # and 3 would be passed to next parameter, `order` print(np.array_equal(b,c)) # True 

¿Cómo es que puedo hacer esto? Sé que si simplemente escribo 2, 3 en un shell de Python, técnicamente es una tupla tanto si uso paréntesis como si no. Pero la comparación anterior parece violar las leyes básicas de cómo los parámetros posicionales se pasan al dictado de los argumentos de palabras clave. Es decir:

 def f(a, b=1, order='c'): print(a) print(b) f((4,3)) print() f(4,3) # (4, 3) # 1 # # 4 # 3 

… y no hay operadores estrella en reshape . (Algo similar a def f(*a, order='c') anterior.)

Con la forma en que los parámetros están vinculados con los métodos normales de Python, no debería funcionar, pero el método no es un método de Python en absoluto. Numpy es un módulo de extensión para CPython, y numpy.ndarray.reshape se implementa en C.

Si observa la implementación, el parámetro de order solo se lee como un argumento de palabra clave. Un argumento posicional nunca estará vinculado a él, a diferencia de un método normal de Python donde el segundo argumento posicional estaría vinculado a un order . El código C intenta generar el valor para newshape partir de todos los argumentos posicionales.

No hay nada mágico en marcha. La firma de la función simplemente no coincide con la documentación. Esta documentado como

 ndarray.reshape(shape, order='C') 

pero está escrito en C, y en lugar de hacer el equivalente C-api de

 def reshape(self, shape, order='C'): 

hace el equivalente en C-api de la manipulación manual *args y **kwargs . Puede echar un vistazo en numpy/core/src/multiarray/methods.c . (Tenga en cuenta que el equivalente en C-api de def reshape(self, shape, order='C'): tendría la misma firma de nivel C que el código actual, pero usaría de inmediato algo como PyArg_ParseTupleAndKeywords para analizar el argumentos en lugar de hacer el manejo manual.)