2009-08-02 15 views
23

Esiste un modo semplice e rapido per utilizzare sum() con valori non interi?python's sum() e valori non interi

Così posso usare in questo modo:

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 

Ho provato l'override __add__ e __int__ ecc, ma io non ho trovato una soluzione ancora

EDIT:

Il soluzione è da implementare:

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

come suggerito nel suo post. Ma, come sempre, tutte le strade portano a Roma, ma credo che questa sia la soluzione migliore in quanto non ho bisogno __add__ nella mia classe

risposta

25

E 'un po' complicato - la somma() funzione prende l'avvio e lo aggiunge a quello successivo e così via

È necessario implementare il metodo __radd__:

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

Penso che implementare __radd__ sia la soluzione migliore, dal momento che non necessita di map(), reduce() o importa moduli aggiuntivi. – sloth

5

Prova:

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

sum() funziona probabilmente più veloce, ma è è specializzato solo per i numeri integrati. Naturalmente devi ancora fornire un metodo per aggiungere i tuoi oggetti Foo(). Così pieno Esempio:

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

da functools importare ridurre # PY3 –

+0

Questa è la soluzione più generica, che funziona per qualsiasi tipo implementando '__add__', compresi quelli che non sono progettati per funzionare con' sum (...) ', come le quantità con unità nella libreria' pint'. – gerrit

3

provare a utilizzare il metodo di __int__ e poi mappare ogni elemento nella lista per la funzione int per ottenere i valori fuori:

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

Oppure, se non si vuole importare nulla,

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

un altro piccolo vantaggio è che non si deve dichiarare necessariamente un add metodo come parte dei tuoi oggetti Foo, se questa è l'unica circostanza in cui vorresti fare l'aggiunta. (Ma probabilmente non sarebbe male per definire aggiungere per flessibilità futura.)

16

potrebbe anche essere necessario per implementare la funzione __radd__, che rappresenta "reverse aggiungere" e si chiama quando gli argomenti non possono essere risolti in la direzione "avanti". Ad esempio, x + y viene valutato come x.__add__(y) se possibile, ma se questo non esiste, Python prova y.__radd__(x).

Poiché la funzione sum() inizia con il numero intero 0, la prima cosa che fa è cercare di valutare:

0 + Foo(3) 

che richiederà di implementare Foo.__radd__.