[PYTHON] Portée variable

J'étais confus quant à la portée des variables Python, alors je l'ai réétudiée. (Vérifié avec CPython 2.7.10 et 3.4.3)

Définition des fonctions

Puisque la définition de fonction crée une étendue, les variables déclarées dans la définition de fonction ne sont pas visibles de l'extérieur.

func_def.py


def func():
    i = 0
print(i)
% python2.7 func_def.py
Traceback (most recent call last):
  File "func_def.py", line 3, in <module>
    print(i)
NameError: name 'i' is not defined

% python3.4 func_def.py
Traceback (most recent call last):
  File "func_def.py", line 3, in <module>
    print(i)
NameError: name 'i' is not defined

C'est basique. Cette propriété empêche la propagation d'effets involontaires à l'intérieur et à l'extérieur de la fonction.

fermeture

Lors du référencement d'une variable qui n'est pas définie dans la définition de fonction, s'il existe une variable avec le même nom dans la même portée que la définition de fonction, elle y est liée, donc même si la même variable existe dans l'environnement au moment de l'appel, elle n'est pas affectée.

closure.py


def getfunc():
    def func():
        return s
    s = "value@def"  #J'ose l'écrire derrière
    return func
f = getfunc()
s = "value@call"
print(f())
% python2.7 closure.py
value@def

% python3.4 closure.py
value@def

Idem avec lambda

closure_lambda.py


def getfunc():
    func = lambda: s
    s = "value@def"  #J'ose l'écrire derrière
    return func
f = getfunc()
s = "value@call"
print(f())
% python2.7 closure_lambda.py
value@def

% python3.4 closure_lambda.py
value@def

Variables non liées

S'il n'est pas lié lors de la définition de la fonction, il est fait référence à l'environnement au moment de l'appel. Veuillez noter qu'une transmission involontaire d'effets peut se produire.

func_call.py


def getfunc():
    def func():
        return s
    return func
f = getfunc()
s = "value@call"
print(f())
% python2.7 func_call.py
value@call

% python3.4 func_call.py
value@call

pour déclaration

Étant donné que l'instruction for ne crée pas de portée, les variables de boucle et les variables déclarées en interne sont partagées en dehors de l'instruction for.

for.py


for i in range(3):
    s = "value inside loop"
print(i)
print(s)
% python2.7 for.py
2
value inside loop

% python3.4 for.py
2
value inside loop

Notez qu'il est erroné d'assumer le comportement de C ++ pour (i ne peut être référencé que dans la boucle).

for.cpp


#include <stdio.h>
int main()
{
  const char *s = NULL;
  for (int i = 0; i < 3; i++) {
    s = "value inside loop";
  }
  printf("%d\n", i);
  printf("%s\n", s);
  return 0;
}
% clang for.cpp
for.cpp:8:18: error: use of undeclared identifier 'i'
  printf("%d\n", i);
                 ^
1 error generated.

Notation d'inclusion de liste

Les variables utilisées dans la notation d'inclusion de liste sont divulguées vers l'extérieur dans python2.

référence:

list_comprehension.py


[i for i in range(3)]
print(i)
% python2.7 list_comprehension.py
2

Ne sachant pas cela, je me demandais pourquoi j'ai fait une erreur de programmation et je n'ai pas eu d'erreur pendant un moment. De plus, il ne fuit pas dans python3.

% python3.4 list_comprehension.py
Traceback (most recent call last):
  File "list_comprehension.py", line 2, in <module>
    print(i)
NameError: name 'i' is not defined

application?

Profitant de la portée des variables qui ont fui, il est écrit en Le lambda de Python est cassé! Vous pouvez voir pourquoi le problème se produit

lambda_in_list_comprehension.py


fs = [(lambda: i) for i in range(3)]
print(fs)
print(fs[0](),fs[1](),fs[2]())
i += 1
print(fs[0](),fs[1](),fs[2]())
% python2.7 lambda_in_list_comprehension.py
[<function <lambda> at 0x10fd67f50>, <function <lambda> at 0x10fd70050>, <function <lambda> at 0x10fd700c8>]
(2, 2, 2)
(3, 3, 3)

En d'autres termes, nous générons trois fonctions lambda, mais nous lions un seul i.

définir la notation d'inclusion

Dans le cas de la notation d'inclusion d'ensemble, la variable ne s'échappe pas (comme dans la notation d'inclusion de liste).

set_comprehension.py


{i for i in range(3)}
print(i)
% python2.7 set_comprehension.py
Traceback (most recent call last):
  File "set_comprehension.py", line 2, in <module>
    print(i)
NameError: name 'i' is not defined

% python3.4 set_comprehension.py
Traceback (most recent call last):
  File "set_comprehension.py", line 2, in <module>
    print(i)
NameError: name 'i' is not defined

Recommended Posts

Portée variable
À propos de la portée des variables. .. ..
Variable de soulignement Python
NameError, variable non définie
# Principes de base de Python (portée)
EP 15 Savoir comment les fermetures interagissent avec une portée variable