pytho-函数作用域
函数外部可以使用函数内部的变量?
def test():
a = 10
print(a)
test() #
print(a) # NameError: name 'a' is not defined
代码运行的形式
python解释器开始运行之后,会在内存里面开辟一个空间,每当遇见一个变量的时候,就把变量名和值的对应关系进行记录下来,但是遇见函数的时候,解释器只是象征性的将函数名读到内存中,表示知道这个函数的存在了,至于函数内部的变量和逻辑,解释器根本不关心。
等到执行调用函数的时候,python解释器会在开辟一块内存空间来存储这个函数里面的内容,这个时候,才关心还是里面的这些变量,而函数中的变量会存储在新开辟的内存空间里面,函数中的变量只能在函数内部进行使用,并且会随着函数执行完毕,这块内存中的所以的内容也会被清空。
"存放名字和值的关系"的空间起了一个名字,叫作:命名空间。
代码开始,创建和存储"变量名和值的关系"的空间叫作全局命名空间。
在函数中运行开辟的临时的空间叫作局部命名空间。
命名空间和作用域
命名空间有下面的几种形式:
- 全局命名空间
- 局部命名空间
- 内置命名空间
内置命名空间
内置命名空间中存放了python解释器为我们提供的名字:input,print,str,list,tuple...它们都是我们熟悉的,拿过来就可以用的方法。
三种命名空间之间的加载与取值顺序:
加载顺序:内置命名空间(程序运行前进行加载)\(\Rightarrow\)全局命名空间(程序运行中:从上到下加载)\(\Rightarrow\)局部命名空间(程序运行中:调用才加载)
取值顺序:
- 在局部调用的时候:局部命名空间\(\Rightarrow\)全局命名空间\(\Rightarrow\)内置的命名空间
- 在全局调用的时候:全局命名空间\(\Rightarrow\)内置命名空间
在寻找变量时,从小范围去寻找,一层一层到大范围去找寻。
作用域作用域
按照生效范围分为:
- 全局作用域:包括了名称空间和全局名称空间,在整个文件的任意位置都有被引用,全局有效
- 局部作用域:局域名称空间,只能在局部内生效。
global和nonlocal关键字
global:
- 声明一个全局变量
- 在局域作用域想要对全局变量进行修改时,则可以使用global关键字(只能是字符串和数字)
def test():
global a
a = 10
print(a) # 10
test()
print(a) # 10
count = 1
def search():
global count
count = 2
search()
print(count) # 2
nonlocal:
- 不能修改全局变量。
- 在局部作用域中,对父级作用域(或者更外层作用域非全局作用域)的变量进行引用和修改,并且引用的哪层,从那层及以下此变量全部发生改 变。
def add_b():
b = 42
def do_global():
b = 10
print(b)
def dd_nonlocal():
nonlocal b
b = b + 20
print(b)
dd_nonlocal()
print(b)
do_global()
print(b)
add_b()
总结:
1、局部作用域改变全局变量用global, global同时还可以定义新的全局变量
2、内层函数改变外层函数变量用nonlocal, nonlocal不能定义新的外层函数变量,只能改变已有的外层函数变量
函数的嵌套和作用域链
def f1():
print("1111")
def f2():
print("2222")
def f3():
print("3333")
f3()
f2()
f1() # 1111 2222 3333
**********************************************************************************
def f1():
def f2():
def f3():
print("in f3")
print("in f2")
f3()
print("in f1")
f2()
f1()
def f1():
def f2():
def f3():
print("in f3")
print("in f2")
f3()
print("in f1")
f2()
f1()
函数的作用域链
def f1():
a = 1
def f2():
print(a)
f2()
f1() # 1
函数名的本质
函数名本质上就是函数的内存地址
def f1():
a = 1
def f2():
print(a)
f2()
print(f1) # <function f1 at 0x000001ADCD0D3E18> # 内存地址
1函数是可以被引用的
def func():
print("function")
f = func
f() # function
2.可以被当作容器类型的元素
def func1():
print("function1")
def func2():
print("function2")
def func3():
print("function3")
def func4():
print("function4")
func_list = [func1, func2, func3, func4]
for i in func_list:
i()
'''
function1
function2
function3
function4
'''