Python3 函数作用域
一 LEGB
什么是LEGB?
L:local 函数内部作用域
E:enclosing 函数内部与内嵌函数之间
G:global 全局作用域
B:build-in 内置作用域
顺序是什么?
跟名字一样,Python在函数里面的查找分为4种,称之为LEGB,也正是按照这种顺序来查找的。
首先,是local,先查找函数内部
然后,是enclosing,再查找函数内部与嵌入函数之间(是指在函数内部再次定义一个函数)
其次,是global,查找全局
最后,是build-in,内置作用域
实例(Python3.0+):
name = 'wangyw' def foo(): name = 'maoj' def bar(): print(name) # 打印的name时就用到函数作用域,它会找本函数中是否存在此变量,如不存在找上级函数中是否存在,逐级上寻找变量,直到找到变量位置。 return bar foo() a = foo() # 把执行foo()函数得到的return返回值赋值给a,也就是把返回值bar赋值给a print(a) # 此时打印的是a(bar)的内存地址 a() # 相当于执行bar()
二 函数变量
我们通常把定义在函数外的变量成为全局变量,定义在函数内的变量称为局部变量,顾名思义,全局变量的作用域是整个代码段,局部变量的作用域就只是在它所属的代码段,变量只在它的作用域里有效。
通过实例,我们可以进一步理解下,全局和局部的概念。
实例1(Python3.0+):
count = 10 # 全局变量 def print_local(): count = 5 # 局部变量,这个count覆盖了全局变量count,这2个是不同的变量。 print(count) def print_global(): print(count) # 这里的count是最上面的全局变量噢 print_local() print_global() """ 运行结果: >> 5 >> 10 """
global
- 函数中引用修改全局变量
实例(Python3.0+):
count = 10 def foo(): global count # 告知程序count是全局变量 print(count) count = 7 # 修改全局变量count的值 print(count) foo() """ 运行结果: >> 10 >> 7 """
nonlocal
- 引用修改父级局部变量
实例(Python3.0+):
count = 100 def foo(): count = 10 def inter(): nonlocal count # 引用父级局部变量 print(count) count = 20 print(count) inter() print(count) foo() """ 运行结果: >> 10 >> 20 >> 20 """
小结:
- 变量查找顺序:LEGB,作用域局部>外层作用域>当前模块中的全局>Python内置作用域。
- 只有模块、类以及函数才能引用新作用域。
- 对于一个变量,内部作用域声明会覆盖外部变量,不直接声明,就会使用外部作用域的变量。
- 内部作用域要修改外部作用域变量的值时,全局变量要使用golbal关键字,嵌套作用域变量要使用nonlocal关键字,nonlocal是Python3新增的关键字,有了这个关键字,就能完美的实现闭包了。
- 如果函数的内容中无global关键字,优先读取局部变量;如无局部变量,则读取全局变量,但无法对全局变量进行重新赋值(name="ffff"),对于可变类型(列表,字典),可以对内部元素进行操作。
错误实例1:
name = "lvcm" def count(): print(name) name = "wangyw" print(name) count() """ 运行结果: >> UnboundLocalError: local variable 'name' referenced before assignment """
错误实例1,函数中没有使用global关键字,print(name),读取的是全局变量name,不能对全局变量name进行修改,但如果name是可变类型(字典,列表)时,可以对全局变量进行修改操作。
实例:
name = ['zhubj','age'] def count(): print(name) name.append("wangyw") # 列表的所有方法都可以使用 print(name) count() print(name) """ 运行结果: >>> ['zhubj', 'age'] >>> ['zhubj', 'age', 'wangyw'] >>> ['zhubj', 'age', 'wangyw'] """
错误实例2:
name = ['name','age'] def count(): name = "wangyw" global name print(name) count() """ 运行结果: >>> SyntaxWarning: name 'name' is assigned to before global declaration global name 备注:函数中使用global声明全局变量时,global之前不能定义与全局变量同名的局部变量,否则会报错。为了避免报错,代码中全局变量使用大写,局部变量使用小写 """