定义域

局部定义域:(local)L
外部嵌套定义域:(Enclosing function local)E
函数定义所在模块定义域:(Global module)G
内置定义域:(Build)B
变量的查找原则和c++等语言类似,L->E->G->B

示例

有一些在我看来和c++相比不太习惯的用法

1
2
3
4
5
6
7
8
9
10
11
12
13
i=1
def func():
i=5
def funcin():
i=6
print(i)
funcin()
print(i)
# print(locals())
# print(globals())

func()
print(i)

由于python不需要声明变量,赋值即是创建变量。变量在局部赋值,如果不加声明,那么会创建新的局部变量,不会对上一层的变量修改。所以结果第一次输出6, 第二次输出5,第三次输出1。

尽管如此,未定义以前赋值也会报错,也就是说无法直接赋值,赋值只会创建新的局部变量,比如以下程序就会报错(local variable ‘i’ referenced before assignment)

1
2
3
4
5
6
7
8
9
10
11
i=1
def func():
i=5
def funcin():
i=i+1
print(i)
funcin()
print(i)

func()
print(i)

怎么解决呢,添加关键字global

1
2
3
4
5
6
7
8
9
10
11
12
i=1
def func():
i=5
def funcin():
global i
i=i+1
print(i)
funcin()
print(i)

func()
print(i)

输出

1
2
3
2
5
2

发现输出了最外围的i,内部的没有变化。那如果我就是想要修改上层函数的变量呢?用nonlocal关键字(python3)

1
2
3
4
5
6
7
8
9
10
11
12
i=1
def func():
i=5
def funcin():
nonlocal i
i=i+1
print(i)
funcin()
print(i)

func()
print(i)

输出

1
2
3
6
6
1

增加一层嵌套,看下怎么访问上上层,必须每层都声明。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
i=1
def func():
i=5
def funcin():
nonlocal i
def funcindeep():
nonlocal i
i=i+1
print(i)
funcindeep()
funcin()
print(i)
func()
print(i)

输出

1
2
3
6
6
1

但是在使用过程会发现奇怪的一点,在局部的定义的变量在全局可以直接使用。

if True:
    i=10
    print("---"+str(i))
print(i)

for j in range(10):
    print("---"+str(j))
print(j)

输出为:

---10
10
---0
---1
---2
---3
---4
---5
---6
---7
---8
---9
9

说明函数的定义规则不符合循环分支结构,在其内部定义的变量为全局变量。