Domanda

map() scorre l'elenco come farebbe "for"?C'è un valore nell'usare map vs for?

Se è così, in questo momento il mio codice è simile a questo:

for item in items:
    item.my_func()

Se ha senso, vorrei renderlo map().È possibile?Com'è un esempio?

È stato utile?

Soluzione

Potresti usare map invece del for loop che hai mostrato, ma dal momento che non sembra che tu utilizzi il risultato di item.my_func(), questo è non consigliato. map dovrebbe essere usato se vuoi applicare una funzione senza effetti collaterali a tutti gli elementi di un elenco.In tutte le altre situazioni, utilizzare un ciclo for esplicito.

Inoltre, a partire da Python 3.0 map restituisce un generatore, quindi in quel caso map non si comporterà allo stesso modo (a meno che non valuti esplicitamente tutti gli elementi restituiti dal generatore, ad es.a chiamata list su di essa).


Modificare: kibibu chiede nei commenti un chiarimento sul perché mapIl primo argomento di non dovrebbe essere una funzione con effetti collaterali.Proverò a rispondere a questa domanda:

map è pensato per passare una funzione f in senso matematico.In tali circostanze non importa in quale ordine f viene applicato agli elementi del secondo argomento (purché siano restituito nel loro ordine originale, ovviamente).Ancora più importante, in quelle circostanze map(g, map(f, l)) è semanticamente equivalente a map(lambda x: g(f(x)), l), indipendentemente dall'ordine in cui f E g vengono applicati ai rispettivi input.

Ad esempio, non importa se map restituisce e iteratore o un elenco completo contemporaneamente.Tuttavia, se f e/o g causare effetti collaterali, allora questa equivalenza è garantita solo se la semantica di map(g, map(f, l)) sono tali che in qualsiasi fase g viene applicato al primo N elementi restituiti da map(f, l) Prima map(f, l) si applica f al (n+1)​primo elemento di l.(Intendendo che map deve eseguire l'iterazione più pigra possibile, cosa che fa in Python 3, ma non in Python 2!)

Fare un ulteriore passo avanti:anche se assumiamo l'implementazione di Python 3 di map, l'equivalenza semantica potrebbe facilmente fallire se l'output di map(f, l) è ad es.attraversato itertools.tee prima di essere fornito all'esterno map chiamata.

La discussione di cui sopra può sembrare di natura teorica, ma man mano che i programmi diventano più complessi, diventa più difficile ragionarci su e quindi più difficile eseguirne il debug.Garantire che alcune cose siano invarianti allevia in qualche modo il problema e può di fatto prevenire un'intera classe di bug.

Da ultimo, map ricorda a molte persone la sua controparte veramente funzionale in vari linguaggi (puramente) funzionali.Passargli una "funzione" con effetti collaterali confonderà quelle persone.Pertanto, vedere come alternativa (cioè utilizzare un ciclo esplicito) non è più difficile da implementare rispetto a una chiamata a map, si consiglia vivamente di limitarne l'uso map a quei casi in cui la funzione da applicare non provoca effetti collaterali.

Altri suggerimenti

È possibile scrivere questo usando la mappa in questo modo:

map(cls.my_func, items)

sostituendo CLS con la classe degli elementi che si effettua l'iterazione.

Come già detto da Stephan202, questo è non raccomandato in questo caso.

Come regola generale, se si vuole creare un nuovo elenco, applicando una funzione ad ogni elemento della lista, utilizzare carta. Questo ha comportato la il che significa che la funzione non ha alcun effetto collaterale, e quindi si potrebbe (potenzialmente) eseguire la mappa in parallelo.

Se non si desidera creare un nuovo elenco, o se la funzione ha effetti collaterali, utilizzare un ciclo for. Questo è il caso nel tuo esempio.

C'è una leggera differenza semantica, che probabilmente è chiuso nelle specifiche linguaggio Python. Il mappa è esplicitamente parallelizzabile, mentre per solo in situazioni particolari. Il codice può rompere dalla per , ma solo scappare con l'eccezione di mappa .

A mio parere mappa non dovrebbe garantire anche ordine di applicazione, mentre la funzione per must. AFAIK nessuna implementazione pitone è attualmente in grado di fare questo auto-parallelizzazione.

È possibile passare il tuo map a qualche quadro fresco filettata o multiprocessing O calcolo distribuito se è necessario. Disco è un esempio di distribuzione resistenti ai guasti quadro basato, erlang-e-pitone. Ho configurato su 2 scatole di 8 core e ora il mio programma viene eseguito 16 volte più veloce, grazie al cluster Disco, però ho dovuto riscrivere il mio programma da list comprehension e cicli for a Map / Reduce.

E 'lo stesso accordo per scrivere un programma utilizzando per i loop e list comprehension e mappa / ridurre, ma quando ne avete bisogno per funzionare su un cluster, si può fare quasi gratis se si è utilizzato mappa / ridurre. Se non l'hai fatto, bene, si dovrà riscrivere.

Attenzione: per quanto ne so, python 2.x restituisce un elenco invece di un iteratore dalla mappa. Ho sentito questo può essere aggirato utilizzando iter.imap() (mai usato però).

Utilizzare un esplicita per-ciclo quando non hai bisogno di una lista di risultati indietro (ad es. Le funzioni con effetti collaterali).

Utilizzare un elenco di comprensione quando si ha bisogno di un elenco di risultati di nuovo (per es. Le funzioni che restituiscono un valore basato direttamente sull'ingresso).

Usa mappa () quando si sta cercando di convincere gli utenti Lisp che Python vale la pena utilizzare. ;)

Il vantaggio principale di map è quando vuoi ottenere il risultato di alcuni calcoli su ogni elemento di una lista.Ad esempio, questo snippet raddoppia ogni valore in un elenco:

map(lambda x: x * 2, [1,2,3,4])  #=> [2, 4, 6, 8]

È importante notarlo map restituisce un nuovo elenco con i risultati.Non modifica l'elenco originale in vigore.

Per fare la stessa cosa con for, dovresti creare un elenco vuoto e aggiungere una riga aggiuntiva al file for body per aggiungere il risultato di ciascun calcolo al nuovo elenco.IL map la versione è più concisa e funzionale.

Mappa a volte può essere più veloce per le funzioni built-in di codifica manualmente un ciclo for. Prova di temporizzazione mappa (str, gamma (1000000)) a fronte di un simile ciclo for.

map(lambda item: item.my_func(), items)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top