2010-09-10 13 views
5

Ho scritto una riga di codice utilizzando lambda per chiudere un elenco di oggetti di file in python2.6:Impossibile chiudere il file in modo funzionale in python3.1?

map(lambda f: f.close(), files) 

Funziona, ma non lo fa in python3.1. Perché?

Ecco il mio codice di prova:

import sys 

files = [sys.stdin, sys.stderr] 

for f in files: print(f.closed) # False in 2.6 & 3.1 

map(lambda o : o.close(), files) 

for f in files: print(f.closed) # True in 2.6 but False in 3.1 

for f in files: f.close()   

for f in files: print(f.closed) # True in 2.6 & 3.1 

risposta

6

map restituisce una lista in Python 2, ma un iteratore in Python 3. Quindi, i file verranno chiusi solo se eseguire iterazioni sul risultato.

Non applicare mai map o simili funzioni "funzionali" a funzioni con effetti collaterali. Python non è un linguaggio funzionale e non lo sarà mai. Utilizzare un ciclo for:

for o in files: 
    o.close() 
+0

Nota anche che 2to3 lo rileva e automaticamente elencherà (...) la richiesta di mappa per te, forzando una valutazione immediata. –

+3

'Non applicare mai mappe o funzioni "funzionali" simili a funzioni con effetti collaterali. Python non è un linguaggio funzionale e non lo sarà mai. ' Non vedo perché questo non sarebbe un buon consiglio anche se Python fosse un linguaggio funzionale. Semplicemente non serve usare la mappa se non si utilizzerà il risultato, in nessuna lingua. – sepp2k

+0

Nelle lingue puramente funzionali le funzioni non hanno effetti collaterali, quindi una funzione 'close()' non può esistere. – Philipp

4

Perché mappa in Python 3 è un iteratore pigro. Citando the docs:

Restituisce un iteratore che applica la funzione a ogni elemento di iterabile, ottenendo i risultati.

E.g. in Python 2, map(f, seq) equivale a [f(i) for i in seq], ma in Python 3 è (f(i) for i in seq) - sintassi leggermente diversa, ma semantica molto diversa. Per rendere la variante della mappa funzionante, è necessario consumare l'iteratore. Ergo, è più semplice (e più idiomatico: mappa, comprensione e generatori non dovrebbero avere effetti collaterali!) Per usare un ciclo esplicito.

+1

A mio parere avrebbero dovuto lasciare 'map()' da solo e reso il metodo itaprools del metodo 'imap()' un built-in. Invece tutti i "loro" hanno introdotto una maggiore incompatibilità cambiando ciò che fa un built-in esistente. – martineau

+0

Inoltre, lasciando 'map()' da solo e rendendo 'imap()' un built-in avrebbe seguito meglio la filosofia "Explicit is better than implicit". – martineau

Problemi correlati