2012-06-09 10 views
7

Es posible sobrecargar [] (__getitem__) el operador Python y los métodos de cadena utilizando la referencia de memoria inicial.Sobrecarga [] Operador python y métodos de encadenamiento que utilizan una referencia de memoria

imaginar que tienen una clase Math que acepta una lista de números enteros, como esto:

class Math(object): 
    def __init__(self, *args, **kwargs): 
     assert(all([isinstance(item, int) for item in list(args)])) 
     self.list = list(args) 

    def add_one(self): 
     for index in range(len(self.list)): 
      self.list[index] += 1 

y quiero hacer algo como esto:

instance = Math(1,2,3,4,5) 
instance[2:4].add_one() 

Después de ejecutar este código instance.list debe ser [1,2,4,5,5], ¿es esto posible?

Sé que podría hacer algo como add_one(2,4), pero este no es el estilo de API que me gustaría tener si es posible.

Gracias

Respuesta

9

Como se menciona Winston, es necesario implementar un objeto auxiliar:

class Math(object): 
    def __init__(self, *args, **kwargs): 
     self.list = list(args) 

    def __getitem__(self, i): 
     return MathSlice(self, i) 

class MathSlice(object): 
    def __init__(self, math, slice): 
     self.math = math 
     self.slice = slice 

    def add_one(self): 
     for i in xrange(*self.slice.indices(len(self.math.list))): 
      self.math.list[i] += 1 


instance = Math(1,2,3,4,5) 
instance[2:4].add_one() 

print instance.list 

Cómo se comparte el objeto de matemáticas con el objeto MathSlice depende de lo que desea la semántica que ser si el objeto cambia de matemáticas.

+0

'xrange (* self.slice.indices (len (self.math.list)))' se siente terriblemente antiponético. ¿Hay una mejor manera? – Eric

+0

Además, está mezclando 'self.fields' y' self.list' – Eric

+0

@Eric: eliminé el Math.add_one innecesario, y sí que el xrange (* ...) parece muy engorroso, pero no sé una forma más corta. –

5

Numpy hace algo como esto.

El método __getitem__ recibirá un objeto slice. Ver http://docs.python.org/reference/datamodel.html para más detalles. Tendrá que devolver un nuevo objeto, pero implemente ese objeto de manera que modifique la lista original.

+0

Gracias Winston por su respuesta. Estoy aceptando la respuesta de Ned, porque él está dando más detalles de implementación y creo que otros usuarios lo encontrarán más útil. Pero aprecio tu respuesta. – maraujop

Cuestiones relacionadas