2011-03-29 7 views
7

Tengo una subclase matriz, donde algunos de los atributos adicionales solamente son válidos para la forma original del objeto. ¿Hay alguna manera de asegurarse de que todas las operaciones de cambio de forma de matriz devuelvan una matriz numpy normal en lugar de una instancia de mi clase?Cómo hacer una serie subclase numpy donde todas las operaciones de cambio de forma de devolver una matriz normal de

Ya he escrito array_wrap, pero esto no parece tener ningún efecto en operaciones como np.mean, np.sum o np.rollaxis. Todos estos simplemente devuelven una instancia de mi clase.

import numpy as np  

class NewArrayClass(np.ndarray): 
    __array_priority__ = 3.0 
    def __array_wrap__(self, out_arr, context=None): 
     if out_arr.shape == self.shape: 
      out = out_arr.view(new_array) 
      # Do a bunch of class dependant initialization and attribute copying. 
      # ... 
      return out 
     else: 
      return np.asarray(out_arr) 

A = np.arange(10) 
A.shape = (5, 2) 
A = arr.view(NewArrayClass) 
# Would like this to be np.ndarray, but get new_array_class. 
print type(np.sum(A, 0)) 

Calculo que tengo que hacer algo en __new__ o __array_finalize__, pero no tienen ni idea de qué.

Actualización: Después de leer detenidamente la documentación numpy en subclases (http://docs.scipy.org/doc/numpy/user/basics.subclassing.html), las operaciones de toda gama Desformación están haciendo el 'nuevo modelo de' operación. Entonces la pregunta es: ¿cómo se hace que la operación 'nueva de la plantilla' devuelva instancias de ndarray en lugar de instancias de mi clase? Hasta donde puedo decir, __new__ nunca se llama dentro de estas funciones.

Alternativa: Asumiendo lo anterior no es posible, ¿cómo me identifico al menos en __array_finalize__ la nueva plantilla de la operación (en contraposición a ver casting)? Esto al menos me permitiría desreferenciar algunos atributos que se copian por referencia. También podría establecer una bandera o algo que diga a la nueva instancia que su forma no es válida.

Respuesta

1

Si no está presentando ningún miembro nuevo en sus instancias NewArrayClass, puede reasignar el atributo __class__ de las instancias devueltas.

A.__class__ = np.ndarray 

El punto es por qué le gustaría hacer tal cosa. ¿Participas en un estricto control de tipos en otro lugar? Podrías ir mucho más con el tipado de patos.

+0

Tengo un montón de métodos en mi clase que generarán una excepción si la matriz tiene una forma incorrecta. Quiero que estos métodos sean inaccesibles. – kiyo

+0

Así que el método descrito puede funcionar para usted. Los métodos introducidos por 'NewArrayClass' no se aplicarán de ninguna manera a la instancia con' __class__' modificado. – janislaw

+0

No creo que se te permita hacer esto con clases definidas en extensiones C, como 'np.ndarray'. Obtengo la asignación 'TypeError: __class__: solo para tipos de montón'. –

Cuestiones relacionadas