Accès à l'espace de nom local d'une fonction englobante
Est-ce qu'on peux accéder a l'espace de nom local de la fonction englobante ?
Dans l'exemple ci-dessous, est ce que Python me permet de récupérer l'espace local de func1, depuis func2 ?
def func1():
a = 2
def func2():
print("Comment print le contenu de l'espace de nom local de func1 depuis func2 ?")
func2()
func1()
Je me pose la question parce que si depuis func1 je peux peux print la variable a alors qu'elle n'est pas déclarée dans func2, c'est bien que Python à un mécanisme sous-jacent qui lui permet d'accéder à l'espace local de func1. Et j'aimerai savoir (par curiosité), si je peux le faire manuellement, et si oui, comment ?
Ca fait 2 jours que je tourne et retourne les concepts de namespace, scope et closure dans tous les sens pour essayer d'y voir plus clair. C'est vraiment pas évident à comprendre mais je crois avoir pigé le truc. J'ai fait le petit bout de code suivant pour essayer de bien comprendre. Je l'avoue, ça ne sert strictement à rien de faire tout ça, mais c'est pour essayer de comprendre ce qui se passe sous le capot.
Tout ce que je vais écrire ci-dessous est à prendre avec pincettes, car c'est ma compréhension du sujet à l'instant T, et il est tout à fait possible que je me sois planté (je suis preneur de retours / conseils si jamais je raconte des bêtises).
1) Ma question initiale était : est-il possible depuis func2, d'afficher dynamiquement le contenu de l'espace local de func1.
Réponse : non ce n'est pas possible, parce que l'espace local de func1 a été détruit au moment ou la fonction a terminée son exécution.
2) De ce constat découle une seconde question : Comment est ce possible que func1 puisse lire le contenu de la variable b alors que l'espace local de func1 a été détruit ?
Réponse : Comme func2 est une fonction imbriquée dans func1, le mécanisme de closure se met en place et uniquement les variables de func1 étant référencée dans func2 vont être capturées dans la closure de func1. C'est notamment pour ça que la variable a serait accessible depuis func2 si jamais je rajoutais un print(a).
3) Du coup nouvelle question : est-ce que je peux dynamiquement afficher le contenu de tous mes objets stockés dans le scope de la closure de func2 depuis func2 ?
Réponse : Oui, comme le montre le code ci-dessous
def func1():
a = 2
b = 3
c = "test"
def func2():
# seul a et c seront "sauvegardés" dans la closure de func2. Comme b n'est jamais référencé, il ne sera plus accessible
nonlocal a
_ = c
# on créé dynamiquement un dictionnaire qui contiendra tous les objets de ma closure ainsi que leurs valeurs
dict_var_closure = {}
for index, var_name in enumerate(func2.__code__.co_freevars):
dict_var_closure[var_name] = func2.__closure__[index].cell_contents
print(dict_var_closure)
return func2
func1()()
Ce code va me retourner : {'a': 2, 'c': 'test', 'func2': <function func1.<locals="">.func2 at 0x00000205886ADEE0>}
J'arrive donc bien à retrouver dynamiquement mes variables a et c. En revanche, b n'est plus accessible car elle n'est jamais utilisée dans func2.
Est-ce que les explications ci-dessous sont correctes ou est-ce que je me plante sur certains aspects ?
Inscris-toi
(c'est gratuit !)
Tu dois créer un compte pour participer aux discussions.
Créer un compte