2009-08-02 13 views
23

¿Existe una manera simple y rápida de usar sum() con valores no enteros?suma de python() y valores no enteros

Así que puedo utilizar de esta manera:

class Foo(object): 
    def __init__(self,bar) 
     self.bar=bar 

mylist=[Foo(3),Foo(34),Foo(63),200] 
result=sum(mylist) # result should be 300 

He intentado anular __add____int__ y etc, pero no lo he encontrado todavía una solución

EDIT:

El la solución es implementar:

def __radd__(self, other): 
    return other + self.bar 

como Will sugirió en su publicación. Pero como siempre, todos los caminos conducen a Roma, pero creo que esta es la mejor solución, ya que no necesito en mi clase __add__

Respuesta

25

Es un poco complicado - la suma() toma la salida y lo añade a la siguiente y así sucesivamente

que necesita para implementar el __radd__ método:

class T: 
    def __init__(self,x): 
     self.x = x 
    def __radd__(self, other): 
     return other + self.x 

test = (T(1),T(2),T(3),200) 
print sum(test) 
+0

Creo que la implementación de __radd__ es la mejor solución, ya que no necesita map(), reduce() ni importa módulos adicionales. – sloth

5

Probar:

import operator 
result=reduce(operator.add, mylist) 

suma() funciona probablemente más rápido, pero está especializado solo para números integrados. Por supuesto, todavía debe proporcionar un método para agregar sus objetos Foo(). Tan llena ejemplo:

class Foo(object): 
    def __init__(self, i): self.i = i 
    def __add__(self, other): 
     if isinstance(other, int): 
      return Foo(self.i + other) 
     return Foo(self.i + other.i) 
    def __radd__(self, other): 
     return self.__add__(other) 

import operator 
mylist = [Foo(42), Foo(36), Foo(12), 177, Foo(11)] 
print reduce(operator.add, mylist).i 
+0

de functools importar reducir # AP3 –

+0

Esta es la solución más genérica, que funciona para cualquier tipo que implemente '__add__', incluidos aquellos que no están diseñados para trabajar con' sum (...) ', como cantidades con unidades en la biblioteca' pinta'. – gerrit

3

intente utilizar el método __int__ y luego el mapeo de cada elemento de la lista a la función int para obtener los valores de salida:

class Foo(object): 
    def __init__(self,bar): 
     self.bar = bar 
    def __int__(self): 
     return self.bar 

mylist = [Foo(3),Foo(34),Foo(63),200] 
result = sum(map(int,mylist)) 
print(result) 
5

O si no desea importar nada,

result=reduce((lambda x,y:x+y), mylist 

Otra pequeña ventaja es que usted no tiene que declarar necesariamente un añadir método como parte de sus objetos Foo, si esta es la única circunstancia en la que le gustaría hacer más. (Pero probablemente no estaría de más añadir definir de flexibilidad en el futuro.)

16

También puede ser necesario para implementar la función __radd__, que representa "revertir añadir" y se llama cuando los argumentos no se pueden resolver de la dirección "hacia adelante". Por ejemplo, x + y se evalúa como x.__add__(y) si es posible, pero si eso no existe, Python intenta y.__radd__(x).

Dado que la función sum() comienza con el número entero 0, lo primero que hace es tratar de evaluar:

0 + Foo(3) 

lo que requerirá que implemente Foo.__radd__.

Cuestiones relacionadas