À des fins de test, je souhaite exécuter directement une fonction définie dans une autre fonction.
Je peux accéder à l'objet de code de la fonction enfant, via le code (func_code) de la fonction parent, mais lorsque je l'exécute, je n'obtiens aucune valeur de retour.
Existe-t-il un moyen d'obtenir la valeur de retour à partir du code exécuté?
Oui, vous devez avoir l'affectation dans l'instruction exec
:
>>> def foo():
... return 5
...
>>> exec("a = foo()")
>>> a
5
Ceci n’est probablement pas pertinent pour votre cas, car il est utilisé dans des tests contrôlés, mais faites attention à utiliser exec
avec une entrée définie par l’utilisateur.
Quelque chose comme ça peut marcher:
def outer():
def inner(i):
return i + 10
for f in outer.func_code.co_consts:
if getattr(f, 'co_name', None) == 'inner':
inner = type(outer)(f, globals())
# can also use `types` module for readability:
# inner = types.FunctionType(f, globals())
print inner(42) # 52
L'idée est d'extraire l'objet de code de la fonction interne et de créer une nouvelle fonction à partir de celle-ci.
Un travail supplémentaire est requis lorsqu'une fonction interne peut contenir des variables libres. Vous devrez également les extraire et les transmettre au constructeur de la fonction dans le dernier argument (closure
).
Bien que ce soit la bête la plus laide jamais vue par l'humanité, voici comment vous pouvez le faire en utilisant une variable globale dans votre appel à la fonction exec:
def my_exec(code):
exec('global i; i = %s' % code)
global i
return i
Cela utilise mal les variables globales pour faire passer vos données à la frontière.
>>> my_exec('1 + 2')
3
Inutile de dire que vous devriez jamais autoriser toute entrée d’utilisateur pour l’entrée de cette fonction, car cela pose un risque extrême pour la sécurité.