楔子
1 >>> def my_max(x,y): 2 ... m = x if x>y else y 3 ... 4 >>> my_max(10,20) 5 >>> print(m) 6 Traceback (most recent call last): 7 File "<stdin>", line 1, in <module> 8 NameError: name 'm' is not defined
报错了!错误是“name 'm' is not defined”。变量m没有被定义。。。为啥?我明明定义了呀!
在这里我们首先回忆一下python代码运行的时候遇到函数是怎么做的。
从python解释器开始执行之后,就在内存中开辟了一个空间
每当遇到一个变量的时候,就把变量名和值之间的对应关系记录下来。
但是当遇到函数定义的时候解释器只是象征性的将函数名读入内存,表示知道这个函数的存在了,至于函数内部的变量和逻辑解释器根本不关心。
等执行到函数调用的时候,python解释器会再开辟一块内存来存储这个函数里的内容,这个时候,才关注函数里面有哪些变量,而函数中的变量会存储在新开辟出来的内存中。函数中的变量只能在函数的内部使用,并且会随着函数执行完毕,这块内存中的所有内容也会被清空。
“存放名字与值的关系”的空间起了一个名字——叫做命名空间
代码在运行伊始,创建的存储“变量名与值的关系”的空间叫做全局命名空间,在函数的运行中开辟的临时的空间叫做局部命名空间
一、命名空间和作用域
(1)内置命名空间--Python解释器
就是python解释器一启动就可以使用的名字存储在内置命名空间中,内置的名字在启动解释器的时候被加载进内存里。
(2)全局命名空间
是在程序从上到下被执行的过程中依次加载进内存的,放置了我们设置的所有变量名和函数名。
(3)局部命名空间--函数
就是函数内部定义的名字,当调用函数的时候才会产生这个名称空间,随着函数执行的结束 这个命名空间就又消失了。
(4)三者的关系
- 在局部:可以使用全局、内置命名空间中的名字。
- 在全局:可以使用内置命名空间中的名字,但是不能用局部中使用。
- 在内置:不能使用局部和全局的名字的。
(5)栗子
1 def max(l) 2 print("in max func") 3 print(max([1,2,3]))
结果:in max func
- 在正常情况下,直接使用内置的名字。但当我们在全局定义了和内置名字空间中同名的名字时,会使用全局的名字。
- 当我自己有的时候 我就不找我的上级要了。如果自己没有 就找上一级要 上一级没有再找上一级 如果内置的名字空间都没有就会报错。
- 多个函数应该拥有多个独立的局部名字空间,不互相共享。
二、作用域
- 全局作用域 —— 作用在全局 —— 内置和全局名字空间中的名字都属于全局作用域 ——globals()
- 局部作用域 —— 作用在局部 —— 函数(局部名字空间中的名字属于局部作用域) ——locals()
三、数据修改
对于不可变数据类型,在局部可是查看全局作用域中的变量,但是不能直接修改。如果想要修改,需要在程序的一开始添加global声明,如果在一个局部(函数)内声明了一个global变量,那么这个变量在局部的所有操作将对全局的变量有效。
1 a=1 2 def func(): 3 global a 4 a=2 5 6 func() 7 print(a) #结果a=2