作用域
作用域是一个变量的可见范围叫做这个变量的作用域
>>> x = 1 定义在全局作用域中
>>> def inc(): 函数内部是一个局部作用域,是不能直接使用全局作用域的变量
... x += 1
...
>>> inc()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in inc
UnboundLocalError: local variable 'x' referenced before assignment
变量的作用域为定义变量同级的作用域
>>> def fn():
... xx = 1 定义一个局部变量,在只能在函数体内部使用
... print(xx)
...
>>> fn()
1
>>> xx 局部变量只能在同级的变量作用域中使用,也可以说是,局部变量不能在全局作用域中使用
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'xx' is not defined
>>> def fn1():
... print(xx) 局部作用域中定义的变量,只能在当前局部作用域使用,不能再其他的局部作用域使用
...
>>> fn1()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in fn1
NameError: name 'xx' is not defined
函数嵌套演示作用域
>>> def fn():
... xx = 1
... print(xx)
... def inner(): 上级作用域对下级作用域可见
... print(xx)
... inner()
...
>>> fn()
1
1
>>> def fn(): 上级作用域对下级作用域是只读可见的,下级作用域没有操作上级作用域的权限
... xx = 1
... print(xx)
... def inner():
... xx = 2 赋值及定义,在下级作用域里面重新定义了xx变量
... inner()
... print(xx)
...
>>> fn()
1
1
不同作用域变量是不可见的,但是下级作用域可以对上级作用域的变量只读可见
全局变量
定义一个全局变量
>>> xx = 1
>>> def fn():
... global xx 使用global可以提升变量作用域为全局变量
... xx += 1
...
>>> fn()
>>> xx
2
不管在外层有没有定义都可以提升变量作用域,若是有则是提升,若是没有变量,则是定义一个全局变量
>>> def fn():
... global yy
... yy = 3
...
>>> fn()
>>> yy
3
仅仅使用global,是无法单独定义全局变量的
>>> def fn():
... global zz
...
>>> fn()
>>> zz
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'zz' is not defined
global 对作用域的提升只对本作用域有用
>>> def fn():
... global zz global只能在本作用域生效,如果需要在其他非全局作用域中使用的话,也需要做同样的global提升
... zz = 3
... print(zz)
...
>>> def fn2():
... zz += 1 这里进行作用域运算时不行的,因为zz只是只读可见的权限,没有操作的权限
... print(zz)
...
>>> fn()
3
>>> fn2()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in fn2
UnboundLocalError: local variable 'zz' referenced before assignment
>>> def fn2():
... global zz 要使用其他同级作用域中的global变量,也需要global提升一下
... zz += 1
... print(zz)
...
>>> fn2()
4
除非你清楚的知道global会带来什么,并且明确的知道,非global不行,否则不要使用global
在Python程序中不到非用不可的情况下的话,尽量不要使用global因为global的副作用是很大的,容易造成变量数据的混乱
默认参数的作用域
在Python中一切皆是对象,函数也是对象,函数参数则是函数对象的属性,所以函数参数的作用域会伴随着函数的整个生命周期
>>> def fn(x=[]): 当函数没有释放内存的时候,那么当前函数的生命周期就没有结束,参数则会持续添加
... x.append(1)
... print(x)
...
>>>fn()
[1]
>>> fn()
[1, 1]
>>> fn()
[1, 1, 1]
>>> fn.__defaults__ 在函数的生命周期内,函数的默认参数都会保存在__defaults__方法中,元组的形式存储,根据参数的位置存储
([1, 1, 1],)
对于全局作用域里面的函数,初始化的几种方式:
- 重新定义函数
- del删除杉树
- 程序结束退出
对于局部作用域里面的函数,初始化的几种方式:
- 重新定义函数
- del 删除函数
- 上级作用域被销毁
当使用可变类型作为默认参数默认值时,需要特别注意
通常使用一个可变类型作为默认参数时,会使用None来代替
尽可能使用不可变类型作为默认参数的默认值