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)
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.
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
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
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.
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
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.
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