Intente crear dinámicamente dos funciones definidas en una cadena. Código:
def main():
fns = '''
def plus_one(x):
return x + 1
def plus_two(x):
return plus_one(x) + 1
'''
exec(fns)
result = eval('plus_two(11)')
print(result)
if __name__ == '__main__':
main()
Guardar este código en dyn_code.py
un archivo con nombre y ejecutarlo genera el siguiente error:
python dyn_code.py
Traceback (most recent call last):
File "dyn_code.py", line 19, in <module>
main()
File "dyn_code.py", line 14, in main
result = eval('plus_two(11)')
File "<string>", line 1, in <module>
File "<string>", line 7, in plus_two
NameError: name 'plus_one' is not defined
El problema aquí plus_one
no plus_two
se puede resolver internamente. Sabes
plus_one
en sí está bien aquí y se puede llamar con los resultados correctos. Sabes
¿Alguien puede decirme cómo inyectar código como este en un espacio de nombres local? Específicamente, quiero crear dos funciones, una de las cuales hace referencia a la otra. Sabes
Utilicé intencionalmente las formas más abiertas de exec
y eval
, sabía cómo restringirlas, etc. También verifiqué exec
que ambas funciones existen en el espacio de nombres local después de la llamada. Sabes
¡Lo que es aún más frustrante es que el código funciona bien en la sesión del intérprete! Es decir, después de exec
inyectar estas dos funciones en el espacio de nombres del intérprete, plus_two
no hay problemas en tiempo de ejecución. Sabes
Idealmente, me gustaría evitar el uso de funciones en escenarios de funciones.
def plus_two(x):
def plus_one(x):
return x + 1
return plus_one(x) + 1
Esta técnica realmente funciona, pero necesito dos funciones independientes nombradas explícitamente.
Es necesario exec()
agregar un diccionario a la llamada a globals()
. También puedes omitir la llamada eval a plus_two, así:
def main():
exec('def plus_one(x):\n return x + 1\n\ndef plus_two(x): return plus_one(x) + 1', globals())
print(plus_two(11))
if __name__ == '__main__':
main()