[PYTHON] J'ai étudié à quoi ressemble la lunette

Lorsque je regardais l'implémentation de la fermeture, je ne savais pas pourquoi cela fonctionnait, alors j'ai regardé à quoi ressemble la portée. Je pense que c'est très basique, mais je n'ai pas trouvé d'article sur le net qui pourrait comprendre à quoi ressemble la lunette. À la suite de l'avoir déplacé, j'ai pensé que c'était difficile à expliquer.

Portée vue du niveau supérieur

Vérifions l'état des variables globales et locales avec le code suivant.

Confirmation (1)

from pprint import pprint
print "-----globals----->>>"
pprint(globals())
print "-----locals----->>>"
pprint(locals())

Résultat d'exécution


-----globals----->>>
{'__builtins__': <module '__builtin__' (built-in)>,
 '__doc__': None,
 '__file__': 'tes002.py',
 '__name__': '__main__',
 '__package__': None,
 'pprint': <function pprint at 0x02222770>}
-----locals----->>>
{'__builtins__': <module '__builtin__' (built-in)>,
 '__doc__': None,
 '__file__': 'tes002.py',
 '__name__': '__main__',
 '__package__': None,
 'pprint': <function pprint at 0x02222770>}

Dans cet état, le contenu affiché pour les variables globales et locales est le même. Que se passe-t-il si vous définissez une variable?

Confirmation (2)

from pprint import pprint
a = 123
pprint(globals())
print "-----globals----->>>"
print "-----locals----->>>"
pprint(locals())

Résultat d'exécution


-----globals----->>>
{'__builtins__': <module '__builtin__' (built-in)>,
 '__doc__': None,
 '__file__': 'tes002.py',
 '__name__': '__main__',
 '__package__': None,
 'a': 123,
 'pprint': <function pprint at 0x02222770>}
-----locals----->>>
{'__builtins__': <module '__builtin__' (built-in)>,
 '__doc__': None,
 '__file__': 'tes002.py',
 '__name__': '__main__',
 '__package__': None,
 'a': 123,
 'pprint': <function pprint at 0x02222770>}

Dans l'environnement d'exécution de script de niveau supérieur, le contenu de sortie de locals () et globals () est le même. Les variables définies sont présentes dans les deux sorties. (*** Globals () et local () sont jugés pour afficher les noms de la portée globale et de la portée locale, respectivement, et ce qui suit est décrit **)

De plus, pprint est dans la sortie de globals (). (aussi dans les locaux ()) Les modules et fonctions importés par import seront inclus dans la portée globale. (Ceux qui peuvent être directement référencés au niveau supérieur sont dans la portée globale)

Que se passe-t-il si vous définissez une fonction et regardez la portée à partir de la fonction?

Portée vue de la fonction

##Vérification(3)
a = 123
def tes001():
	b = 234
	print "-----globals----->>>"
	pprint(globals())
	print "-----locals----->>>"
	pprint(locals())
tes001()

Résultat d'exécution


-----globals----->>>
{'__builtins__': <module '__builtin__' (built-in)>,
 '__doc__': None,
 '__file__': 'tes002.py',
 '__name__': '__main__',
 '__package__': None,
 'a': 123,
 'pprint': <function pprint at 0x02422770>,
 'tes001': <function tes001 at 0x02422BF0>}
-----locals----->>>
{'b': 234}

La variable b définie dans le bloc fonction existe dans la portée locale mais pas dans la portée globale.

Définissons maintenant les variables après avoir affiché le contenu de locals () et globals () dans le bloc fonction.

Confirmation (4)

a = 123
def tes001():
	print "-----globals----->>>"
	pprint(globals())
	print "-----locals----->>>"
	pprint(locals())
	b = 234
tes001()

Résultat d'exécution


-----globals----->>>
{'__builtins__': <module '__builtin__' (built-in)>,
 '__doc__': None,
 '__file__': 'tes002.py',
 '__name__': '__main__',
 '__package__': None,
 'a': 123,
 'pprint': <function pprint at 0x02222770>,
 'tes001': <function tes001 at 0x02222BF0>}
-----locals----->>>
{}

Dans ce cas, la variable b n'est pas non plus dans la portée locale. Que se passe-t-il si vous placez la sortie de locals () avant et après la définition de variable?

Confirmation (5)

a = 123
def tes001():
	print "-----globals----->>>"
	pprint(globals())
	print "-----locals(1)----->>>"
	pprint(locals())
	b = 234
	print "-----locals(2)----->>>"
	pprint(locals())
tes001()

Résultat d'exécution


-----globals----->>>
{'__builtins__': <module '__builtin__' (built-in)>,
 '__doc__': None,
 '__file__': 'tes002.py',
 '__name__': '__main__',
 '__package__': None,
 'a': 123,
 'pprint': <function pprint at 0x02222770>,
 'tes001': <function tes001 at 0x02222BF0>}
-----locals(1)----->>>
{}
-----locals(2)----->>>
{'b': 234}

C'est comme prévu. Il n'est pas dans la sortie avant que la variable ne soit définie, mais dans la sortie après sa définition.

Fonctions Nest pour connaître la portée

Ensuite, imbriquez les définitions de fonction et vérifiez la portée à partir de la fonction interne.

Confirmation (6)

a = 123
def tes001():
	b = 234
	def inner():
		c = 345
		print "-----globals----->>>"
		pprint(globals())
		print "-----locals----->>>"
		pprint(locals())
	inner()
tes001()

Résultat d'exécution


-----globals----->>>
{'__builtins__': <module '__builtin__' (built-in)>,
 '__doc__': None,
 '__file__': 'tes002.py',
 '__name__': '__main__',
 '__package__': None,
 'a': 123,
 'pprint': <function pprint at 0x022226F0>,
 'tes001': <function tes001 at 0x02222BF0>}
-----locals----->>>
{'c': 345}

Il n'y a pas de b dans la portée locale de inner (). Que se passe-t-il si vous faites référence à b dans inner ()? Affichez la sortie des sections locales () avant et après le référencement.

Confirmation (7)

a = 123
def tes001():
	b = 234
	def inner():
		c = 345
		print "-----globals----->>>"
		pprint(globals())
		print "-----locals(1)----->>>"
		pprint(locals())
		print b
		print "-----locals(2)----->>>"
		pprint(locals())
	inner()
tes001()

Résultat d'exécution


-----globals----->>>
{'__builtins__': <module '__builtin__' (built-in)>,
 '__doc__': None,
 '__file__': 'tes002.py',
 '__name__': '__main__',
 '__package__': None,
 'a': 123,
 'pprint': <function pprint at 0x022226F0>,
 'tes001': <function tes001 at 0x02222BF0>}
-----locals(1)----->>>
{'b': 234, 'c': 345}
234
-----locals(2)----->>>
{'b': 234, 'c': 345}

Cette fois, la variable b existe également dans la portée locale avant de référencer la variable b (`` print b ''). Cela semble un peu différent de "confirmation (5)". Le comportement est différent entre la référence et l'affectation. Sensuellement

-----locals(1)----->>>
{'c': 345}
234
-----locals(2)----->>>
{'b': 234, 'c': 345}

Je pensais que ce serait comme ça. Le résultat ci-dessus suppose que la portée locale de la fonction inner () a une portée contenant la variable b avant d'exécuter le code. En premier lieu, la variable b est incluse dans la portée locale même si elle n'est pas définie dans la fonction inner (). Du point de vue du mouvement, lorsque la fonction est imbriquée, lorsque la fonction interne se réfère à une variable indéfinie et définie à l'extérieur, lorsque la fonction interne y fait référence, le contenu de la définition de la fonction externe est copié et la fonction interne est copiée. Définissez la portée locale de. Ce paramètre de portée semble avoir été effectué avant l'exécution du code. Il semble que la valeur initiale de la portée locale est créée avant que la fonction ne soit exécutée.

Examinons la portée lorsque la variable définie à l'extérieur est modifiée avec la fonction à l'intérieur.

Confirmation (8)

a = 123
def tes001():
	b = 234
	def inner():
		c = 345
		print "-----inner: globals----->>>"
		pprint(globals())
		print "-----inner: locals(1)----->>>"
		pprint(locals())
		print b
		b = 777
		print "-----inner: locals(2)----->>>"
		pprint(locals())
	inner()
	print "-----outer: locals(3)----->>>"
	pprint(locals())
tes001()

Résultat d'exécution


-----inner: globals----->>>
{'__builtins__': <module '__builtin__' (built-in)>,
 '__doc__': None,
 '__file__': 'tes002.py',
 '__name__': '__main__',
 '__package__': None,
 'a': 123,
 'pprint': <function pprint at 0x022226F0>,
 'tes001': <function tes001 at 0x02222BF0>}
-----inner: locals(1)----->>>
{'c': 345}
Traceback (most recent call last):
  File "tes002.py", line 19, in <module>
    tes001()
  File "tes002.py", line 16, in tes001
    inner()
  File "tes002.py", line 12, in inner
    print b
UnboundLocalError: local variable 'b' referenced before assignment

Après avoir exécuté ce qui précède, j'ai eu une erreur (Erreur locale non liée). Fait intéressant, le contenu de locals (), qui est d'abord généré par la fonction inner (), n'inclut pas la variable b. Si seule la référence ( print b '') était faite, b était inclus. La seule différence est de savoir si la fonction interne définit les variables définies sur l'extérieur. Après tout, il semble que la portée soit préparée avant d'exécuter le code. Le code fonctionne sur la base de cette portée préparée. Cependant, dans l'exemple ci-dessus, la variable b n'est pas définie dans la portée locale préparée au moment de l'exécution car il existe un code de réglage ( b = 777 '') dans la fonction interne. Dans cet état (la variable b n'est pas dans la portée), une erreur se produit en essayant de faire référence à la variable b.

Organisons les résultats confirmés jusqu'à présent

Si vous organisez le contenu confirmé jusqu'à présent, y compris certaines inférences (spéculation),

Examiner à quoi ressemble la portée lorsqu'une variable globale est référencée et définie dans une fonction

Ensuite, examinons à quoi ressemble la portée lorsque la variable globale est référencée et définie dans la fonction.

Confirmation (8)

a = 123
def tes001():
	print a
	print "-----tes001: globals(1)----->>>"
	pprint(globals())
	print "-----tes001: locals(1)----->>>"
	pprint(locals())
	a = 345
	print "-----tes001: globals(2)----->>>"
	pprint(globals())
	print "-----tes001: locals(2)----->>>"
	pprint(locals())
tes001()
print "-----top: globals(3)----->>>"
pprint(globals())
print "-----top: locals(3)----->>>"
pprint(locals())

Résultat d'exécution


Traceback (most recent call last):
  File "tes003.py", line 15, in <module>
    tes001()
  File "tes003.py", line 5, in tes001
    print a
UnboundLocalError: local variable 'a' referenced before assignment

Dans ce cas, identique à la confirmation (7). UnboundLocalError. Le même comportement lorsque l'étendue globale et l'étendue locale sont mélangées. Dans la fonction tes001 (), attribuer la variable a puis la référencer devrait fonctionner.

Confirmation (9)

a = 123
def tes001():
	print "-----tes001: globals(1)----->>>"
	pprint(globals())
	print "-----tes001: locals(1)----->>>"
	pprint(locals())
	a = 345
	print a
	print "-----tes001: globals(2)----->>>"
	pprint(globals())
	print "-----tes001: locals(2)----->>>"
	pprint(locals())
tes001()
print "-----top: globals(3)----->>>"
pprint(globals())
print "-----top: locals(3)----->>>"
pprint(locals())

Résultat d'exécution


-----tes001: globals(1)----->>>
{'__builtins__': <module '__builtin__' (built-in)>,
 '__doc__': None,
 '__file__': 'tes003.py',
 '__name__': '__main__',
 '__package__': None,
 'a': 123,
 'pprint': <function pprint at 0x02222770>,
 'tes001': <function tes001 at 0x02222BB0>}
-----tes001: locals(1)----->>>
{}
345
-----tes001: globals(2)----->>>
{'__builtins__': <module '__builtin__' (built-in)>,
 '__doc__': None,
 '__file__': 'tes003.py',
 '__name__': '__main__',
 '__package__': None,
 'a': 123,
 'pprint': <function pprint at 0x02222770>,
 'tes001': <function tes001 at 0x02222BB0>}
-----tes001: locals(2)----->>>
{'a': 345}
-----top: globals(3)----->>>
{'__builtins__': <module '__builtin__' (built-in)>,
 '__doc__': None,
 '__file__': 'tes003.py',
 '__name__': '__main__',
 '__package__': None,
 'a': 123,
 'pprint': <function pprint at 0x02222770>,
 'tes001': <function tes001 at 0x02222BB0>}
-----top: locals(3)----->>>
{'__builtins__': <module '__builtin__' (built-in)>,
 '__doc__': None,
 '__file__': 'tes003.py',
 '__name__': '__main__',
 '__package__': None,
 'a': 123,
 'pprint': <function pprint at 0x02222770>,
 'tes001': <function tes001 at 0x02222BB0>}

Cela a bien fonctionné. Dans la sortie de tes001: globals (2), a vaut 123 et dans la sortie de tes001: locals (2) 345. Dans tes001 (), la variable locale a est réécrite, donc la valeur de a lors du retour au niveau supérieur reste la valeur (123) avant l'appel de la fonction. J'ai en quelque sorte compris la théorie, mais cela me semble un peu étrange. Supprimez l'instruction d'impression et essayez d'organiser le code quand cela fonctionne et quand cela ne fonctionne pas.

Organiser le code pour les fonctions qui accèdent aux variables définies en tant que variables globales

Si ça marche (1)

a = 123
def tes001():
	print a
tes001()

Si ça marche (2)

a = 123
def tes001():
	a = 345
	print a
tes001()

Si ça ne marche pas

a = 123
def tes001():
	print a			#UnboundLocalError
	a = 345
tes001()

J'ai fait divers mouvements et donné les raisons des résultats de l'opération, mais en regardant ce qui précède, c'est encore difficile à comprendre. J'aimerais enquêter un peu plus, mais ça s'allonge, alors je vais m'arrêter ici. Je pense que je peux expliquer la mise en œuvre des fermetures.

Recommended Posts

J'ai étudié à quoi ressemble la lunette
J'ai étudié le mécanisme de connexion flask!
J'ai étudié la superposition de l'arborescence des appareils
J'ai compté les grains
J'ai étudié l'algorithme d'apprentissage de renforcement du trading d'algorithmes
J'ai essayé de simuler la propagation de l'infection avec Python
Je ne savais pas comment utiliser l'instruction [python] for
J'ai étudié le prétraitement qui peut être fait avec PyCaret
J'ai essayé de résumer comment utiliser à nouveau le référentiel EPEL
J'ai examiné l'arborescence des appareils
Comment utiliser le générateur
J'ai tweeté depuis le terminal!
J'ai essayé de toucher l'API Qiita
J'ai essayé la bibliothèque changefinder!
J'ai étudié la sortie http de Fluentd
Comment utiliser le décorateur
Comment augmenter l'axe
J'ai téléchargé la source python
Comment démarrer la première projection
J'ai lu l'article de SHAP
J'ai appris comment la télécommande infrarouge fonctionne avec Raspberry Pi
J'ai étudié la méthode X-means qui estime automatiquement le nombre de clusters
J'ai résumé comment changer les paramètres de démarrage de GRUB et GRUB2
J'ai étudié le comportement de la différence entre lien dur et lien symbolique
J'ai étudié la relation entre le LSTM avec état de Keras et l'état caché