一个标识符的可见范围,就是标识符的作用域。一般常说的是变量的作用域。
先看一段代码
# -*- coding:utf-8 -*- x=5 def foo(): print(x) foo()
1 x=5 2 def foo(): 3 x+=1 4 print(x) 5 foo()
问:x到底可见不可见?
这里就引入2个概念
全局作用域 --global
在整个程序运行环境中可见。
局部作用域-- local
在函数,类等内部可见。局部变量使用范围不能超过其所在的局部作用域。
回到上面的函数
第一段代码中x=5定义在函数外部,相当全局作用域,在整个程序运行环境中可见。所以第1段程序是没有问题的。
第2段代码会报本地变量未赋值被引用。Why?赋值即定义,x+=1相当于在函数内重新定义了1个局部变量x,那么foo内部所有X都是这个局部变量X,但是X没完成赋值就被右边拿来做加1操作了(赋值语句先执行等号右边的)。
嵌套函数
eg1
1 # -*- coding:utf-8 -*- 2 def outer1(): 3 o=65 4 def inner(): 5 print("inner {}".format(o)) 6 print(chr(o)) 7 print("outer {}".format(o)) 8 inner() 9 10 outer1()
输出结果:
outer 65
inner 65
A
eg2
1 # -*- coding:utf-8 -*- 2 def outer2(): 3 o=65 4 def inner(): 5 o=67 6 print("inner {}".format(o)) 7 print(chr(o)) 8 print("outer {}".format(o)) 9 inner() 10 11 outer2()
输出结果:
outer 65
inner 67
C
从嵌套结构例子可以看出:
外层变量作用域在内层作用域可见;
内层作用域inner中,如果定义了o=67,相当于当前作用域重新定义了一个新的变量o,但是这个o并没有覆盖外层作用域outer中的o。
全局变量Global
1 # -*- coding:utf-8 -*- 2 x=5 3 def foo(): 4 global x 5 x+=1
使用global关键字的变量,将foo内的x声明为使用外部的全部作用域中定义X。全局作用域中必须要有X的定义。
1 # -*- coding:utf-8 -*- 2 def foo(): 3 global x 4 x=20 5 x+=1
使用global关键字的变量,将foo内的x声明为使用外部的全部作用域中定义X。
但是X=20赋值即定义,x在内部作用域为一个外部作用的变量赋值,所有x+=1不会报错。注意,这里的x的作用域还是全局的。
Global的使用原则
- 外部作用域变量在内部作用域可见,但是也不要在这个内部的局部作用域中直接使用(因为函数的目的就是为了封装,尽量与外界隔离);
- 如果函数需要使用外部全局变量,请使用函数的形参传参解决;
- 一句话不用global。
闭包
自由变量:未在本地作用域中定于的变量。例如定义在内层函数的外层函数的作用域中的变量。
闭包:就是一个概念,出现在嵌套函数中。指的是内层函数引用到了外层函数的自由变量就形成了闭包。
1 # -*- coding:utf-8 -*- 2 def couter(): 3 c=[0] 4 def inc(): 5 c[0]+=1 6 return c[0] 7 return inc 8 foo=couter() 9 print(foo(),foo()) 10 c=200 11 print(foo())
输出结果:
1 2
3
第5行是对变量的元素的修改,而不是对变量C赋值。
c=200和couter中的c不一样,inc引用的是自由变量couter中的c。