2011-10-13 6 views
21

Ho bisogno di fare qualcosa che è funzionalmente equivalente a questo:La funzione mappa di Python può chiamare le funzioni membro dell'oggetto?

for foo in foos: 
    bar = foo.get_bar() 
    # Do something with bar 

Il mio primo istinto è stato quello di utilizzare map, ma questo non ha funzionato:

for bar in map(get_bar, foos): 
    # Do something with bar 

è quello che sto cercando di realizzare possibile con map? Ho invece bisogno di usare una comprensione delle liste? Qual è l'idioma più pitonico per questo?

+3

perché non si basta usare una lista di comprensione? – agf

risposta

35

sia con lambda:

for bar in map(lambda foo: foo.get_bar(), foos): 

o con methodcaller:

import operator 
get_bar = operator.methodcaller('get_bar') 
for bar in map(get_bar, foos): 

o con un generatore di espressione:

for bar in (foo.get_bar() for foo in foos): 
+8

In ordine inverso di come sono Pythonici. – agf

+12

Inoltre, 'map (Foo.get_bar, Foos)' 'dove foo' è la classe degli oggetti in' foos'. – agf

+0

ho deciso di andare con il lambda da quando ho capito che avevo bisogno di fare questa trasformazione un paio di posti nel codice, e 'Bar's bisogno di essere stringata e in minuscolo. :) –

7

Volete operator.methodcaller(). O, naturalmente, una lista o una comprensione del generatore.

+0

Immagino che le comprensioni delle liste siano preferite nelle versioni più recenti di Python, giusto? Sarò felice di accettare la tua risposta se la aggiorni per includere il codice di esempio usando un LC per il mio esempio. :) –

+0

@JoshGlover "versioni più recenti di Python"? Tornano almeno a 2.3. – agf

+0

Le comprensioni delle liste sono state aggiunte in Python 2.0. –

1

Questo codice modificato funzionerà:

for bar in map(lambda f: f.get_bar(), foos): 
# Do something with bar 

forniti dall'utente funzione lambda qui. Semplicemente fornendo get_bar non funziona perché è accessibile solo attraverso un'istanza della classe (f.get_bar()), mai da solo.

1

È possibile utilizzare lambda

for bar in map(lambda foo: foo.get_bar(), foos): 
    # Do something with bar 
1

Penso che il modo più pulito è quello di rinunciare al for -loop completamente e utilizzare una lista di comprensione:

bars = [foo.get_bar() for foo in foos] 

Questa risposta è vicino a qualche altro risponde ma differisce dal fatto che la lista viene effettivamente restituita e non utilizzata nel ciclo successivo. A seconda di cosa si fa con bars, si può essere in grado di utilizzare una comprensione di lista lì.

Non credo che la funzione map con lambdas sia particolarmente leggibile, inoltre l'overhead per map è notevole.

Problemi correlati