better - should i use python 3 or 2
Alcance de evaluación en Python 2 vs. 3 (2)
Encontré un comportamiento extraño de evaluación en Python 3: las variables locales no se detectan cuando se llama a eval en una lista de comprensión.
def apply_op():
x, y, z = [0.5, 0.25, 0.75]
op = "x,y,z"
return [eval(o) for o in op.split(",")]
print(apply_op())
Se errores en Python 3:
▶ python --version
Python 3.4.3
▶ python eval.py
Traceback (most recent call last):
File "eval.py", line 7, in <module>
print(apply_op())
File "eval.py", line 5, in apply_op
return [eval(o) % 1 for o in op.split(",")]
File "eval.py", line 5, in <listcomp>
return [eval(o) % 1 for o in op.split(",")]
File "<string>", line 1, in <module>
NameError: name ''x'' is not defined
Y funciona bien en Python 2:
▶ python --version
Python 2.7.8
▶ python eval.py
[0.5, 0.25, 0.75]
Moverlo fuera de la lista de comprensión elimina el problema.
def apply_op():
x, y, z = [0.5, 0.25, 0.75]
return [eval("x"), eval("y"), eval("z")]
¿Es este comportamiento intencional, o es un error?
Hay un problema cerrado en el rastreador de errores para esto: Problema 5242 .
La resolución para este error no se solucionará .
Algunos comentarios del número leídos:
Esto se espera, y no se solucionará fácilmente. La razón es que las comprensiones de listas en 3.x usan un espacio de nombres de función "debajo del capó" (en 2.x, se implementaron como un simple bucle for). Debido a que las funciones internas necesitan saber qué nombres obtener de qué espacio de nombres adjunto, los nombres a los que se hace referencia en eval () no pueden provenir de las funciones adjuntas. Deben ser locales o globales.
eval () probablemente ya sea un hack, no es necesario agregar otro hack para que funcione. Es mejor simplemente deshacerse de eval () y encontrar una mejor manera de hacer lo que quiere hacer.
Si tu quieres:
def apply_op():
x, y, z = [0.5, 0.25, 0.75]
op = "x,y,z"
return [eval(o) for o in op.split(",")]
print(apply_op())
Para trabajar, deberá capturar los locales y los globales, ya que el problema es que eval(o)
es el mismo que tiene eval(o, globals(), locals())
pero a medida que el eval
aparece dentro de la función del generador, los resultados de esos las funciones no son las mismas que eran cuando la eval
no tenía una función de ajuste, así que captelas fuera del generador y utilícelas dentro:
def apply_op():
x, y, z = [0.5, 0.25, 0.75]
op = "x,y,z"
_locals = locals()
_globals = globals()
return [eval(o, _globals, _locals) for o in op.split(",")]
print(apply_op())
O mejor, ya que x,y,z
son locales y las cadenas son solo nombres de variables:
def apply_op():
x, y, z = [0.5, 0.25, 0.75]
op = "x,y,z"
_locals = locals()
return [_locals[o] for o in op.split(",")]
print(apply_op())