一、前言
本节主要内容如下:
1.变量查找顺序
2.全局变量和局部变量
3.nonlocal关键字
4.global关键字和nonlocal关键字的区别:
二、变量查找顺序
函数作用域的LEGB顺序
1.什么是LEGB?
L: local函数内部作用域
E: enclosing函数内部与内嵌函数之间
G: global 全局作用域
B: build-in内置作用域
2.他们是做什么用的?
为什么非要介绍这个呢?或者说他们的作用是什么?
原因是因为我们的在学习python函数的时候,经常会遇到很多定义域的问题,全局变量、局部变量、内部嵌入的函数,等等,
python是如何查找的呢?以及python又是按照什么顺序来查找的呢?这里做一个顺序的说明
3.顺序是什么?
跟名字一样,python在函数里面的查找分为4种,称之为LEGB,也正是按照这种顺序来查找的。
首先,是local,先查找函数内部
然后,是enclosing,再查找函数内部与嵌入函数之间(是指再函数内部再次定义一个函数)
其次,是global,查找全局
最后,是build-in,内置作用域
三、全局变量和局部变量
全局变量是在整个py文件中声明,全局范围内都可以访问
局部变量是在某个函数中声明的,只能在该函数中调用它
我们来看一个小例子:
name = 'chuan'
def func():
name = 'boy'
print('函数内部',name)
func()
print('函数外部',name)
#打印结果:
# 函数内部 boy
# 函数外部 chuan
这里,函数内部的name就是全局变量,函数外部的name就是局部变量
注意:这里有一个问题,我们想函数内部有一个变量name,函数外部也有一个变量name,那么当我在函数内部使用变量name的时候,它是按照什么规则取的name呢?其实,这里就用到了上面说的变量的查找顺序。
1.查看全局变量和局部变量:
name = 'chuan'
def func():
name = 'boy'
print('函数内部',name)
print(locals()) #查看局部变量
print(globals()) #查看全局变量
func()
#打印结果:
# 函数内部 boy
# {'name': 'boy'}
# {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000018E0CA74288>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/Program Files/python老男孩/Day15/01全局变量和局部变量.py', '__cached__': None, 'name': 'chuan', 'func': <function func at 0x0000018E0E6C4678>}
从上面的打印结果,我们就可以看到,局部变量name=‘boy’,
全局变量中可以找到name = ‘chuan’。
注意:这里的是在函数内部使用的locals()和globals()函数,如果是在函数外部使用,就不一样了,函数的局部变量和全局变量是一样的。
2.函数内部使用全局变量,只能查看,不能修改
name = 'chuan'
def func():
print('函数内部',name)
func()
#打印结果是:
#函数内部 chuan
我们看到,我们是可以直接查看全局变量name的
name = 'chuan'
def func():
print('函数内部',name) #这里的name会报错
name = 'xixi'
func()
为什么这里的name会报错呢?因为当你在函数内部写name=‘xixi’,
编译器就会认为你定义了一个局部变量name,而print(‘函数内部’,name)是在name声明之前使用,自然就会报错了
3.使用global在函数内部把变量声明为全局
NAME = '杠精'
def xi():
global NAME#可以理解为是全局变量NAME的引用
print(NAME) #打印结果说明,这个就是上面的全局变量NAME
NAME = '小东北' #修改全局变量
print('我要做',NAME)
xi()
print(NAME)
#打印结果:
#杠精
#我要做 小东北
#小东北
4.函数内部引用可变类型的全局变量
NAME = ['我','哎']
def xi():
NAME.append('你')#此处拿到全局变量,无法对其就行重新赋值 NAME = 'fff' ,但可以添加元素
# NAME = ['love'] 无法重新赋值全局变量
print('我知道',NAME)
xi()
#打印结果:
#我知道 ['我', '哎', '你']
5.一种易错情况
#
name = 'chuan'
def func():
name = 'xixi'
global name
print('函数内部',name)
func()
这种,是会报错的。为什么呢?因为name= 'xixi’相当于声明了一个局部变量并赋值,但是我们又想把这个变量变成外部的全局变量的引用,显然这是不可能的。
四、nonlocal关键字
#2.关键字nonlocal,指定上一级变量
# NAME = '钢梁'
#
# def xi():
# name = '机智'
# def ha():
# nonlocal name#指定上一级变量
# name = '冷静'
#
# ha()
# print(name)
#
# print(NAME)
# xi()
# print(NAME)
五、global关键字和nonlocal关键字的区别
1.global可以用在任何地方,包括最上层函数中和嵌套函数中,即使之前未定义该变量,
def global_test():
global gcount #在之前未定义该变量
gcount = 1
print(gcount)
global_test() #1
2.global修饰后也可以直接使用,而nonlocal关键字只能作用于嵌套函数中,并且外层函数中定义了相应的局部变量,nonlocal最多找到顶层的函数内局部变量,它不能找全局变量,否则会发生错误
name = 2
def haha():
nonlocal name #没有在嵌套函数内,不能找全局变量(外层嵌套函数没有这个变量自己不能单独定义使用,
# 且nonlocal最多找到顶层的函数内局部变量)
name = 5
print(name)
haha()