2010-09-10 8 views
5

me escribió una línea de código usando lambda para cerrar una lista de objetos de archivo en python2.6:¿No se pudo cerrar el archivo de manera funcional en python3.1?

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

Funciona, pero no lo hace en python3.1. ¿Por qué?

Aquí está mi código de prueba:

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 

Respuesta

6

map devuelve una lista en Python 2, pero un iterador en Python 3. Así que los archivos se cerrarán sólo si permite repetir el resultado.

Nunca aplique map o funciones "funcionales" similares a las funciones con efectos secundarios. Python no es un lenguaje funcional, y nunca lo será. Utilice un bucle for:

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

Tenga en cuenta también que 2to3 capta esto, y automáticamente hará una lista (...) de la llamada del mapa para usted, forzando la evaluación inmediata. –

+3

'Nunca aplique el mapa o funciones "funcionales" similares a las funciones con efectos secundarios. Python no es un lenguaje funcional, y nunca lo será ". No veo por qué esto no sería un buen consejo, incluso si Python fuera un lenguaje funcional. Simplemente no tiene sentido usar el mapa si no va a utilizar el resultado, en cualquier idioma. – sepp2k

+0

En las funciones de idiomas puramente funcionales las funciones no tienen efectos secundarios, por lo que una función 'close()' no puede existir. – Philipp

4

Debido mapa en Python 3 es un iterador perezoso. Citando the docs:

Devuelve un iterador que aplica la función a cada elemento de iterable, produciendo los resultados.

E.g. en Python 2, map(f, seq) equivalente a [f(i) for i in seq], pero en Python 3, es (f(i) for i in seq) - sintaxis sutilmente diferente, pero una semántica muy diferente. Para hacer que la variante del mapa funcione, necesitarás consumir el iterador. Ergo, es más simple (y más idiomático: ¡el mapa, la comprensión y los generadores no deberían tener efectos secundarios!) Usar un for-loop explícito.

+1

En mi opinión, deberían haber dejado 'map()' solo e hicieron que el módulo itertools 'imap()' sea un método incorporado. En su lugar, todo lo que 'ellos' hicieron fue introducir una incompatibilidad más importante mediante el cambio de lo que hace un built-in existente. – martineau

+0

Además, dejar 'map()' solo y hacer que 'imap()' sea incorporado habría seguido mejor la filosofía de "Explicit is better than implicit". – martineau

Cuestiones relacionadas