[PYTHON] Variabler Umfang

Ich war verwirrt über den Umfang der Python-Variablen und habe ihn erneut untersucht. (Überprüft mit CPython 2.7.10 und 3.4.3)

Funktionsdefinition

Da die Funktionsdefinition einen Bereich erstellt, sind die in der Funktionsdefinition deklarierten Variablen von außen nicht sichtbar.

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

Es ist einfach. Diese Eigenschaft verhindert die Ausbreitung unbeabsichtigter Effekte innerhalb und außerhalb der Funktion.

Schließung

Wenn beim Verweisen auf eine Variable, die nicht in der Funktionsdefinition definiert ist, eine Variable mit demselben Namen im selben Bereich wie die Funktionsdefinition vorhanden ist, wird sie daran gebunden. Selbst wenn dieselbe Variable zum Zeitpunkt des Aufrufs in der Umgebung vorhanden ist, ist sie nicht betroffen.

closure.py


def getfunc():
    def func():
        return s
    s = "value@def"  #Ich wage es, es hinterher zu schreiben
    return func
f = getfunc()
s = "value@call"
print(f())
% python2.7 closure.py
value@def

% python3.4 closure.py
value@def

Gleiches gilt für Lambda

closure_lambda.py


def getfunc():
    func = lambda: s
    s = "value@def"  #Ich wage es, es hinterher zu schreiben
    return func
f = getfunc()
s = "value@call"
print(f())
% python2.7 closure_lambda.py
value@def

% python3.4 closure_lambda.py
value@def

Ungebundene Variablen

Wenn es bei der Definition der Funktion nicht gebunden ist, wird auf die Umgebung zum Zeitpunkt des Aufrufs verwiesen. Bitte beachten Sie, dass eine unbeabsichtigte Übertragung von Effekten auftreten kann.

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

zur Aussage

Da die for-Anweisung keinen Bereich erstellt, werden sowohl Schleifenvariablen als auch intern deklarierte Variablen außerhalb der for-Anweisung gemeinsam genutzt.

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

Beachten Sie, dass es falsch ist, das Verhalten von C ++ für anzunehmen (ich kann nur innerhalb der Schleife referenziert werden).

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.

Listeneinschlussnotation

In der Listeneinschlussnotation verwendete Variablen werden in python2 nach außen übertragen.

Referenz:

list_comprehension.py


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

Da ich das nicht wusste, fragte ich mich, warum ich einen Programmierfehler gemacht hatte und eine Weile keinen Fehler bekam. Darüber hinaus leckt es nicht in 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

Anwendung?

Es nutzt den durchgesickerten Bereich von Variablen und ist in [Pythons Lambda ist kaputt!] Geschrieben (Http://math.andrej.com/2009/04/09/pythons-lambda-is-broken/). Sie können sehen, warum das Problem auftritt

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)

Mit anderen Worten, wir erzeugen drei Lambda-Funktionen, aber wir binden ein einzelnes i.

Einschlussnotation setzen

Im Fall der eingestellten Einschlussnotation tritt die Variable nicht aus (wie in der Listeneinschlussnotation).

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

Variabler Umfang
Über den Umfang der Variablen. .. ..
Python-Unterstrichvariable
Undefinierte Variable NameError
# Python-Grundlagen (Umfang)
EP 15 Know How Closures interagieren mit variablem Umfang