Que fait l’instruction Python nonlocal
(dans Python 3.0 et versions ultérieures)?
Il n'y a pas de documentation sur le site Web officiel de Python et help("nonlocal")
ne fonctionne pas non plus.
Comparez ceci sans utiliser nonlocal
:
x = 0
def outer():
x = 1
def inner():
x = 2
print("inner:", x)
inner()
print("outer:", x)
outer()
print("global:", x)
# inner: 2
# outer: 1
# global: 0
Pour cela, utiliseznonlocal
, où inner()
's x
est maintenant aussi outer()
' s x
:
x = 0
def outer():
x = 1
def inner():
nonlocal x
x = 2
print("inner:", x)
inner()
print("outer:", x)
outer()
print("global:", x)
# inner: 2
# outer: 2
# global: 0
Si nous utilisions
global
, cela relieraitx
à la valeur proprement "globale":x = 0 def outer(): x = 1 def inner(): global x x = 2 print("inner:", x) inner() print("outer:", x) outer() print("global:", x) # inner: 2 # outer: 1 # global: 2
En bref, cela vous permet d'affecter des valeurs à une variable dans une étendue externe (mais non globale). Voir PEP 3104 pour tous les détails sanglants.
Une recherche sur Google pour "python nonlocal" a abouti à la proposition, PEP 3104 , qui décrit de manière complète la syntaxe et le raisonnement sous-tendant l'instruction. En bref, elle fonctionne exactement de la même manière que l’instruction global
, sauf qu’elle est utilisée pour faire référence à des variables qui ne sont ni globales ni locales à la fonction.
Voici un bref exemple de ce que vous pouvez faire avec cela. Le générateur de compteurs peut être réécrit pour l'utiliser de sorte qu'il ressemble davantage aux idiomes des langues avec des fermetures.
def make_counter():
count = 0
def counter():
nonlocal count
count += 1
return count
return counter
Évidemment, vous pourriez écrire ceci en tant que générateur, comme:
def counter_generator():
count = 0
while True:
count += 1
yield count
Mais bien que ce soit un python parfaitement idiomatique, il semble que la première version serait un peu plus évidente pour les débutants. Utiliser correctement les générateurs, en appelant la fonction retournée, est un point commun de confusion. La première version renvoie explicitement une fonction.
help ('nonlocal') La déclaration
nonlocal
nonlocal_stmt ::= "nonlocal" identifier ("," identifier)*
L'instruction
nonlocal
fait en sorte que les identificateurs répertoriés fassent référence à variables précédemment liées dans la portée englobante la plus proche. C'est important parce que le comportement par défaut pour la liaison est de rechercher le fichier espace de noms local en premier. L'instruction permet au code encapsulé de relier des variables en dehors de la portée locale en plus de la variable globale (module) portée.Noms répertoriés dans une instruction
nonlocal
, contrairement à ceux répertoriés dans unglobal
statement, doit faire référence à des liaisons préexistantes dans un fichier champ englobant (le champ dans lequel une nouvelle liaison doit être créée ne peut pas être déterminé sans ambiguïté).Les noms énumérés dans une instruction
nonlocal
ne doivent pas entrer en collision avec pre - liaisons existantes dans la portée locale.Voir également:
PEP 3104 - Accès aux noms dans les étendues externes
La spécification de l'instructionnonlocal
.Rubriques d'aide connexes: global, NAMESPACES
Source: Référence du langage Python
@ooboo:
Il prend celui "le plus proche" du point de référence dans le code source . Ceci est appelé "cadrage lexical" et est standard depuis plus de 40 ans.
Les membres de la classe Python sont vraiment dans un dictionnaire appelé __dict__
et ne seront jamais atteints par la portée lexicale.
Si vous ne spécifiez pas nonlocal
mais faites x = 7
, il créera une nouvelle variable locale "x" . Si vous spécifiez nonlocal
, il recherchera le "plus proche" "x" et lui assignera cette variable . Si vous spécifiez nonlocal
et il n'y a pas de "x", cela vous donnera un message d'erreur.
Le mot clé global
m’a toujours paru étrange dans la mesure où il ignorera avec joie tous les autres "x" à l’exception du plus externe. Bizarre.
a = 0 #1. global variable with respect to every function in program
def f():
a = 0 #2. nonlocal with respect to function g
def g():
nonlocal a
a=a+1
print("The value of 'a' using nonlocal is ", a)
def h():
global a #3. using global variable
a=a+5
print("The value of a using global is ", a)
def i():
a = 0 #4. variable separated from all others
print("The value of 'a' inside a function is ", a)
g()
h()
i()
print("The value of 'a' global before any function", a)
f()
print("The value of 'a' global after using function f ", a)
Ma compréhension personnelle de la déclaration "nonlocal" (et je m'excuse car je suis novice en Python et en Programmation en général) est que le "non local" est un moyen d'utiliser la fonctionnalité Global dans des fonctions itérées plutôt que dans le corps du code . Une déclaration globale entre les fonctions si vous voulez.
Citation de Référence Python 3 :
L'instruction non locale amène les identificateurs répertoriés à faire référence à des variables précédemment liées dans la portée englobante la plus proche, à l'exclusion des globales.
Comme indiqué dans la référence, dans le cas de plusieurs fonctions imbriquées, seule la variable dans la fonction englobante la plus proche est modifiée:
def outer():
def inner():
def innermost():
nonlocal x
x = 3
x = 2
innermost()
if x == 3: print('Inner x has been modified')
x = 1
inner()
if x == 3: print('Outer x has been modified')
x = 0
outer()
if x == 3: print('Global x has been modified')
# Inner x has been modified
La variable "la plus proche" peut être située à plusieurs niveaux:
def outer():
def inner():
def innermost():
nonlocal x
x = 3
innermost()
x = 1
inner()
if x == 3: print('Outer x has been modified')
x = 0
outer()
if x == 3: print('Global x has been modified')
# Outer x has been modified
Mais cela ne peut pas être une variable globale:
def outer():
def inner():
def innermost():
nonlocal x
x = 3
innermost()
inner()
x = 0
outer()
if x == 3: print('Global x has been modified')
# SyntaxError: no binding for nonlocal 'x' found
avec des fonctions internes 'non locales' (c'est-à-dire des fonctions internes imbriquées), vous pouvez obtenir les droits de lecture & 'write' permission pour cette variable spécifique de la fonction parent externe. Et nonlocal ne peut être utilisé qu’à l’intérieur des fonctions interneseg:
a = 10
def Outer(msg):
a = 20
b = 30
def Inner():
c = 50
d = 60
print("MU LCL =",locals())
nonlocal a
a = 100
ans = a+c
print("Hello from Inner",ans)
print("value of a Inner : ",a)
Inner()
print("value of a Outer : ",a)
res = Outer("Hello World")
print(res)
print("value of a Global : ",a)