名称空间与作用域
什么是名称空间?
存放名字的空间
如果你想访问一个变量值,必须先访问对应的名称空间,拿到名字和对应的地址的绑定关系
名称空间的分类
内置名称空间:
伴随python解释器的启动/关闭而产生/回收,因而是第一个被加载的名称空间,用来存放一些内置的名字
print(print)
#输出结果为
<built-in function print> #built-in内建
全局名称空间:
伴随python文件的开始执行/执行完毕而产生/回收,是第二个被加载的名称空间,文件执行过程中产生的名字都会存放于该名称空间中
x = 1
def foo(x):
if x ==1:
print('苏喂苏喂')
else:
print('啦啦啦')
foo(2)
#输出结果为
啦啦啦
局部名称空间
def foo(x):
y=3 #调用函数时,才会执行函数代码,名字x和y都存放于该函数的局部名称空间中
PS:名称空间的加载顺序是:内置名称空间->全局名称空间->局部名称空间,而查找一个名字,必须从三个名称空间之一找到,查找顺序为:局部名称空间->全局名称空间->内置名称空间。
生命周期
内置名称空间
在python解释器启动时失效,关闭时失效
全局名称空间
当你启动当前py文件时失效,当前页面代码执行结束之后失效
局部名称空间
当你调用当前函数生效,函数体代码执行结束失效
作用域
全局作用域
全局作用域:位于全局名称空间 内置名称空间中的名字属于全局范围,该范围内的名字全局存活(除非被删除,否则在整个文件执行过程中存活) 全局有效(在任意位置都可以使用)
局部作用域
局部作用域:位于局部名称空间中的名字属于局部范围。该范围内的名字临时存活(即在函数调用时临时生成,函数调用结束后就释放) 局部有效(只能在函数内使用)
作用域于名字查找的优先级
在局部作用域查找名字时,起始位置是局部作用域,所以先查找局部名称空间,没有找到,再去全局作用域查找:先查找全局名称空间,没有找到,再查找内置名称空间,最后都没有找到就会返回异常
x = 100 #全局作用域
def foo():
x = 300 #局部作用域
print(x) #在局部找x
foo()
#结果为
300 #先在局部作用域查找名字x,找到后直接返回,不再去找下一个
在全局作用域查找名字时,起始位置便是全局作用域,所以先查找全局名称空间,没有找到,再查找内置名称空间,最后都没有找到就会抛出异常
x = 100
def foo():
x = 300 #在函数调用时产生局部作用域的名字x,只在局部生效,不影响全局
foo()
print(x) #在全局找x,结果100
PS: 可以调用内建函数locals()和globals()来分别查看局部作用域和全局作用域的名字,查看的结果都是字典格式。在全局作用域查看到的locals()的结果等于globals()
函数的嵌套
Python支持函数的嵌套定义,在内嵌的函数内查找名字时,会优先查找自己局部作用域的名字,然后由内而外一层层查找外部嵌套函数定义的作用域,没有找到,则查找全局作用域
x = 1
def outer():
x = 2
def inner():
x = 3
print('inner x:%s' %x)
inner()
print('outer x:%s' %x)
outer()
#结果为
inner x:3
outer x:2
在函数内,无论嵌套多少层,都可以查看到全局作用域的名字,若要在函数内修改全局名称空间中名字的值,当值为不可变类型时,则需要用到global关键字
x = 1
def foo():
global x #声明x为全局名称空间的名字
x = 2
foo()
print(x)
#结果为
2
当实参的值为可变类型时,函数体内对该值的修改将直接反应到原值
num_list = [1, 2, 3]
def foo(num):
num.append(5)
foo(num_list)
print(num_list)
#结果为
[1, 2, 3, 5]
对于嵌套多层的函数,使用nonlocal关键字可以将名字声明为来自外部嵌套函数定义的作用域(非全局)
def f1():
x = 2
def f2():
nonlocal x
x = 3
f2()
print(x)
f1()
#结果为
3
函数对象
函数可以被引用
def sum(x, y):
z = x + y
print(z)
func = sum
print(func(1,2))
#结果为
3
None
函数可以作为容器类型的元素
函数可以作为参数传入另外一个函数
函数的返回值可以是一个函数
1.函数对象
- 是什么?
函数的名字就是函数对象,函数名指向的是函数的内存地址。
- 有什么用?
- 可以被引用
- 可以被当做参数传入
- 可以被当做函数的返回值
- 可以当做参数传入容器中
{"key": func--X0...}
- 函数对象的应用:
补充--》可以优雅地取代if分支
2.函数嵌套
- 函数嵌套定义: 让内层函数封闭起来,不让外部直接调用。
def func1():
def func2():
pass
return func2
func2()
- 函数嵌套调用: 将复杂并且小的功能,在函数内部调用,解决代码结构清晰问题。
def login():
pass
def register():
pass
# 使用func函数的前提是,必须先注册,登录,再使用
def func():
register()
login()
func的逻辑代码
...
3.名称空间与作用域
- 名称空间什么是?
用来存放名字的,名称空间是一个在内存中的空间。
x = 100
def func():
pass
- 内置名称空间:
在python解释器启动时产生,关闭时销毁。
- 全局名称空间:
执行当前的py文件时产生,文件执行结束后销毁,关闭解释器时彻底销毁。
- 局部名称空间:
在执行函数时产生,临时存活,函数调用结束时销毁。
- 名称空间 加载顺序与查找顺序:
- 加载顺序:内置 ---> 全局 ---> 局部
- 查找顺序: 局部 ---> 全局 ---> 内置
- 作用域: 名称空间作用的范围
- 全局:
内置名称空间 + 全局名称空间
- 只要程序一直执行,永久存活,若程序结束,则销毁
- 局部:
局部的名称空间 + 局部的局部的名称空间
- 只要程序一直执行,调用函数时存活,结束时销毁
今日内容