今日内容概要
- 名称空间
- 名字的查找顺序
- python作用域
- global与nonlocal关键字
- 函数名的多种用法
- 函数的嵌套
今日内容详细
一、名称空间
定义:是名称到对象的映射,其实就是存放变量名与变量值绑定关系的地方 类似于民政局、警察局…
名称空间的分类(内置、全局、局部)
-
内置名称空间
python解释器提前给我们定义好的,包含python的内置函数,内置名称空间在 Python 解释器启动时就创建了,直到 Python 解释器退出时内置名称空间才失效。这使得我们可以在程序的任何位置使用内置名称空间内的名称,例如,id(),print()、 len()、 print()、 open()等函数。 -
全局名称空间
也称模块名称空间,在模块内定义的名称,在py文件中编写的代码运行产生的名字都会存到全局名称空间中
name = 'jason' # 变量名name存入全局名称空间
def index(): # 函数名index存入全局名称空间
pass
if True:
a = 111 # 变量名a存入全局名称空间
for i in range(10): # 变量名i存入全局名称空间
pass
while True:
b = 222 # 变量名b存入全局名称空间
- 局部名称空间
在函数(function)或者类(class)被调用时,其内部包含的名称,也就是函数体代码运行产生的都是局部名称空间(代码体部分)函数返回后失效。
def index():
name = 'jason' # name存入局部名称空间
注意:
- 不同的名称空间内的名称不会相互冲突,即是它们采用相同的名称。这也正是名称空间的作用。
二、名字的查找顺序
"""在查找名字的时候 一定要先搞清楚自己在哪个空间"""
1.如果在局部名称空间
局部名称空间 >>> 全局名称空间 >>> 内置名称空间
2.如果在全局名称空间
全局名称空间 >>> 内置名称空间
"""如果函数没有被调用 那么不要去管函数体代码有多复杂 先跳过"""
- 名称空间的加载顺序是:内置名称空间->全局名称空间->局部名称空间,而查找一个名字,必须从三个名称空间之一找到,查找顺序为:局部名称空间->全局名称空间->内置名称空间。
三、python 作用域
作用域就是名称空间能够作用的范围,决定了我们在程序中能否直接使用名称空间中的名称,直接访问的意思是指不需要在名称前添加名称空间的前缀。
-
内置作用域:包括了内置名称,程序任意阶段任意位置均可使用(全局有效)
-
全局作用域:位于全局名称空间、内建名称空间中的名字属于全局范围,该范围内的名字全局存活(除非被删除,否则在整个文件执行过程中存活)、全局有效(在任意位置都可以使用);
-
局部作用域:位于局部名称空间中的名字属于局部范围。该范围内的名字临时存活(即在函数调用时临时生成,函数调用结束后就释放)、局部有效(只能在函数内使用)。
四、 global与nonlocal关键字
1、global
global关键字用来在函数或其他局部作用域中使用全局变量。
- 如果局部要对全局变量修改,应在局部声明该全局变量。
x = 111
def index():
# x = 222 # 直接些的话并不是在修改全局的x 而是在局部名称空间中创建了一个新的x
# 如果想要在局部名称空间中修改全局名称空间中的名字 那么需要使用关键字申明
global x # 申明 修改的是全局x而不是产生新的x
x = 666
print(x)
index()
print(x)
注意:
global会对原来的值(全局变量)进行相应的修改
"""
如果想要在局部修改全局的不可变类型
需要提前加关键字global申明
如果想要在局部修改全局的可变类型
不需要加关键字global申明
"""
2、nonlocal /ˈnɒnˈləʊkəl/
nonlocal声明的变量不是局部变量,也不是全局变量,而是外部嵌套函数内的变量。
def test():
c = 0
def test2():
nonlocal c
c += 1
return c
return test2
a = test()
print(a()) # 1
print(a()) # 2
print(a()) # 3
"""
局部名称空间嵌套的情况下 内层如果想要修改外层
情况1数据是不可变类型
需要使用关键字nonlocal
情况2数据是可变类型
不需要使用关键字nonlocal
"""
五、函数名的多种用法
- 用法1:函数名可以当做变量名赋值
def index():
print('from function index')
print(index)
res = index # 让res也指向函数体代码
res() # index()
- 用法2:函数名还可以当成函数的实参
def index():
print('from index')
def func(a):
print('from func')
print(a)
a()
func(index)
- 用法3:函数名还可以当做函数的返回值
def func():
print('from func')
return index # 将函数名当做返回值
def index():
print('from index')
res = func() # res接收函数名
print(res) # 指向的是index函数的内存地址
res() # index()
- 用法4:函数名可以作为容器类型的元素
def index():
print('from index')
l1 = [11, 22, 33, 44, index]
print(l1)
l1[-1]() # index()
六、函数的嵌套
- 在一个函数中定义了另外一个函数
- 可以进行嵌套调用
def index():
print('aaa') # 第二步
def func():
index() # 第一步
print('bbb') # 第三步
func()
- 函数的定义:可以通过函数套函数的方式来代替之前的多层循环嵌套
def all_func(cmd):
def register():
print('注册功能')
def login():
print('登录功能')
def transfer():
print('转账功能')
if cmd == '1':
register()
elif cmd == '2':
login()
elif cmd == '3':
transfer()
else:
print('哈哈哈 偷懒了 没有用刚刚的功能字典')
all_func('1')
all_func('2')
"""
函数的学习会让我们的代码逻辑更加清晰 更加便于维护
"""