03-python语法之名称空间与作用域
名称空间与作用域
- 参考引用资料:
- https://zhuanlan.zhihu.com/p/108924801
名称空间—namespace
- 对栈区的划分,是存放名字的地方;划分名称空间以后,就可以在栈区中存放相同的名字
三种名称空间用途与存活期
- 内置名称空间
- 存放python解释器内置的名字
- python解释器启动则产生,python解释器关闭则销毁
>>> max <built-in function max> #built-in内建
- 全局名称空间
- 存放顶级代码所产生的名字,只要不是函数内定义的、也不是内置名称空间的,剩下的都是全局名称空间
- 运行python文件时产生,运行完毕则销毁
import sys #模块名sys x=1 #变量名x if x == 1: y=2 #变量名y def foo(x): #函数名foo y=1 def bar(): pass Class Bar: #类名Bar pass
- 局部名称空间
- 在调用函数时,运行函数体代码过程中产生的函数内的名字,比如函数的形参、函数内定义的名字都会被存放于该名称空间中
- 调用函数时存活,调用完毕则销毁
def foo(x): y=3 #调用函数时,才会执行函数代码,名字x和y都存放于该函数的局部名称空间中
三种名称空间加载顺序
- 加载顺序:内置名称空间->全局名称空间->局部名称空间
- 销毁顺序:局部名称空间->全局名称空间->内置名称空间
三种名称空间查找名字的优先级
- 从当前所在位置,向上一层层顺序为:
- 局部名称空间->全局名称空间->内置名称空间。
作用域
全局作用域
- 全局作用域:位于全局名称空间、内建名称空间中的名字属于全局范围
- 该范围内的名字全局存活(除非被删除,否则在整个文件执行过程中存活)、全局有效(在任意位置都可以使用);
局部作用域
- 局部作用域:位于局部名称空间中的名字属于局部范围。该范围内的名字临时存活(即在函数调用时临时生成,函数调用结束后就释放)、局部有效(只能在函数内使用)。
- global
- local
作用域与名字的查找关系
- 在局部作用域查找名字时,起始位置是局部作用域,所以先查找局部名称空间,没有找到,再去全局作用域查找:先查找全局名称空间,没有找到,再查找内置名称空间,最后都没有找到就会抛出异常
x=100 #全局作用域的名字x def foo(): x=300 #局部作用域的名字x print(x) #在局部找x foo()#结果为300
- 在全局作用域查找名字时,起始位置便是全局作用域,所以先查找全局名称空间,没有找到,再查找内置名称空间,最后都没有找到就会抛出异常
x=100 def foo(): x=300 #在函数调用时产生局部作用域的名字x foo() print(x) #在全局找x,结果为100
提示:调用内建函数locals()和globals()来分别查看局部作用域和全局作用域的名字,查看的结果都是字典格式。在全局作用域查看到的locals()的结果等于globals()
- 在函数内,无论嵌套多少层,都可以查看到全局作用域的名字,若要在函数内修改全局名称空间中名字的值,当值为不可变类型时,则需要用到global关键字
x=1 def foo(): global x #声明x为全局名称空间的名字 x=2 foo() print(x) #结果为2
- 对于嵌套多层的函数,使用nonlocal关键字可以将名字声明为来自外部嵌套函数定义的作用域(非全局)
def f1(): x=2 def f2(): nonlocal x x=3 f2() #调用f2(),修改f1作用域中名字x的值 print(x) #在f1作用域查看x f1() #结果 3
函数对象
函数对象的特性
- 函数可以被引用
>>> def add(x,y): ... return x+y ... >>> func=add >>> func(1,2) 3
- 函数可以作为容器类型的元素
>>> dic={'add':add,'max':max}
>>> dic
{'add': <function add at 0x100661e18>, 'max': <built-in function max>}
>>> dic['add'](1,2)
3
- 函数可以作为参数传入另外一个函数
>>> def foo(x,y,func): ... return func(x,y) ... >>> foo(1,2,add) 3
- 函数的返回值可以是一个函数
def bar(): return add func=bar() func(1,2) 3
闭包函数
- 闭包函数=名称空间与作用域+ 函数嵌套+函数对象
- 名字的查找关系,是以函数的定义阶段为准
什么是闭包函数
- “闭”函数指的是该函数是内嵌函数
- “包”函数指的是该函数包含对外层函数作用域的引用(非全局作用域)
- 作用域的关系是在定义完函数时就已经被确定了的,与函数的调用位置无关。
x=1 def f1(): def f2(): print(x) return f2 def f3(): x=3 f2=f1() #调用f1()返回函数f2 f2() #需要按照函数定义时的作用关系去执行,与调用位置无关 f3() #结果为1
- 通过函数的closure属性,查看到闭包函数所包裹的外部变量
>>> func.__closure__ (<cell at 0x10212af78: int object at 0x10028cca0>,) >>> func.__closure__[0].cell_contents 2
- “闭”代表函数是内部的,“包”代表函数外’包裹’着对外层作用域的引用。
- 因而无论在何处调用闭包函数,使用的仍然是包裹在其外层的变量。
闭包函数的应用场景
- 为啥要学习闭包——》2种函数体传参的方式
- 两种为函数体传值的方式:
- 1、直接将值以参数的形式传入;
- 2、将值包给函数
import requests #方式一: def get(url): return requests.get(url).text #方式二: def page(url): def get(): return requests.get(url).text return get
- 提示:requests模块是用来模拟浏览器向网站发送请求并将页面内容下载到本地,需要事先安装:pip3 install requests
如何定义闭包函数

浙公网安备 33010602011771号