Sí, The Zen of Python afirma "Flat es mejor que anidado", sin embargo, no es la única característica que nos importa; también dice "Simple es mejor que complejo". La belleza de with
es que realmente se adhiere a tanto de esos principios como explicaré a continuación.
Cada vez que se encuentre en una reflexión filosófica sobre una función en Python, probablemente valga la pena buscar el Python Enhancement Proposals (PEPs) para leer sobre la motivación detrás de la función. En este caso PEP 343 -- The "with" Statement dice que en la delantera en abstracto:
Este PEP añade una nueva declaración "con" el lenguaje Python para que sea posible factorizar el uso estándar del try/finally declaraciones.
El desglose de las declaraciones try/finally
hace que el código sea más simple y legible.
PEP 343 va más allá de proporcionar un azúcar sintáctico simplista, sin embargo. Se establece un protocolo gestor de contexto:
La expresión que sigue inmediatamente a la con la palabra clave en la declaración es una "expresión de contexto" como la expresión proporciona la clave principal como para el entorno de ejecución del gestor de contexto establece para el duración del cuerpo de la declaración.
Utilizando el protocolo de administrador de contexto, los escritores de API pueden ayudar a ocultar la complejidad y asegurar la adquisición/liberación correcta de los recursos en un contexto de subprocesos múltiples.
Pero la verdadera belleza de la declaración with
se muestra en el ejemplo 12 de PEP 343 lo que explica que:
Un gerente "anidada" contexto que anida automáticamente los suministrados contextos de izquierda a derecha para evitar sangría excesiva.
Mediante el administrador de nested()
contexto se puede tomar el código que se parece a esto:
with a as x:
with b as y:
with c as z:
# Perform operation
y convertirlo en esto:
with nested(a, b, c) as (x, y, z):
# Perform operation
Tenga en cuenta que nested()
se introdujo en Python 2.5, pero a partir de la versión 2.7 está en desuso en favor de esta forma sintáctica del administrador de contexto múltiple:
with a as x, b as y, c as z:
# Perform operation
Claramente, no solo es más simple y más fácil de leer, sino que es mucho más plano que anidado. Por lo tanto, el uso de with
es seguir el camino de 無爲 :)
ACTUALIZACIÓN: En respuesta a comments on Simeon Visser's answer aquí es un ejemplo de cuándo se puede utilizar varios gestores de contexto para abrir más de un archivo a la vez, cuando se quiere comprimir el contenido de dos (o más) archivos juntos de tal manera que si la apertura de uno de los archivos falla que hará que todo el asunto no y cierra correctamente cada archivo que se abrió:
from itertools import izip
with open("/etc/passwd") as a, open("/etc/group") as b, open("/etc/shadow") as c:
for lines in izip(a,b,c):
print map(lambda x: x.split(':')[0], lines)
Ejecutar este ejemplo dos veces; una vez como raíz y una vez como usuario normal. Suponiendo que guarde este archivo como ziptogether.py
primero intente invocarlo como root con sudo python ziptogether.py
y tendrá éxito, pero lo invocará como usuario normal con python ziptogether.py
fallará porque no tiene permisos para leer /etc/shadow
. Cuando falla, el administrador de contexto se asegurará de que los archivos que se abrieron con éxito antes de la falla se cierren correctamente cuando la ejecución se salga del alcance de la declaración with
.
La mayor parte del tiempo dejo que IOError se propague y lo atrape en otro lugar. – Dikei
Por más que estoy en desacuerdo con la premisa de esta pregunta, tengo que darle apoyo para hacer que regrese y vuelva a leer PEP [342] (http: //www.python.org/dev/peps/pep-0342 /) y [343] (http://www.python.org/dev/peps/pep-0343/) – kojiro