目录
一、global与nonlocal
money = 66 # 全局空间
def index():
money = 123
index()
print(money)
![image-20221011145926078](https://pic.jitudisk.com/public/2022/10/11/36fbfe89c4ce0.png)
1.global 局部名称空间直接修改全局名称空间中的数据(不可变类型:整型、字符串和元组)
# 案例1
money = 66 # 全局空间
def index():
global money # global作用 局部名称空间直接修改全局名称空间中(不可变类型)的数据,此时函数体代码内的数据值可以绑定全局名称空间中的变量名
money = 123
index()
print(money) # 此时 money = 123
# 案例2
money = 66 # 全局空间
l1 = [11,22,33]
def index():
l1.append(44) # 此时修改的是全局的l1,列表为可变类型的数据
index()
print(l1)
只有赋值语法才涉及 名称存放 和 在 名称空间查找名字 的问题
2.nonlocal 内层局部名称空间 修改 外层局部名称空间中的数据
# 案例1
# 不使用关键字nonlocal
def index():
name = 'jason'
def inner():
name = 'tom'
inner()
print(name)
index() # jason
# 使用关键字nonlocal
def index():
name = 'jason'
def inner():
nonlocal name # 内层局部名称空间 修改 外层局部名称空间中的数据
name = 'tom'
inner()
print(name)
index() # 函数index 局部名称空间中 name = tom
![image-20221011152158989](https://pic.jitudisk.com/public/2022/10/11/80edea3203974.png)
二、函数名的多种用法
函数可以被当作“数据”来处理,此时可以将函数名看作是变量名
函数名其实绑定的也是一块内存地址,只不过改地址里面存放的不是数据值,而是一段代码,函数名加括号可以去调用这段代码
# 案例1
def index():
print('from index')
print(index) # <function index at 函数名所绑定的内存地址>
1.可以当变量名
1.可以当作变量名赋值
# 案例2
def index():
print('from index')
res = index # 将res绑定向index函数
res() # res也具备调用index的能力
2.可以当函数的参数
2.可以当作函数的参数传值进去
# 案例3
def index():
print('from index')
def func(a):
print(a)
a()
func(index)
![image-20221011153642125](https://pic.jitudisk.com/public/2022/10/11/789d301bc9860.png)
print(函数名) 为打印 该函数的内存地址
print(函数名()) 为打印该函数的返回值
3.可以当函数的返回值
3.可以当作函数的返回值
1)返回值是数据值时,直接返回
# 案例4
def index():
print('from index')
def func():
print('from func')
return 123
res = func()
print(res) # 123
2)返回值是函数名时,赋值于其他变量名可以利用该变量名调用函数
( 1 )两个函数套娃
# 案例5
def index():
print('from index')
def func():
print('from func')
return index
res = func()
print(res)
res() # from index
![10.11 插图4.png](https://pic.jitudisk.com/public/2022/10/11/46bbb074b797b.png)
( 2 )函数嵌套
# 案例6
def index():
print('from index')
def func():
print('from func')
return func
res = index()
print(res)
res() # 让res也绑定向func绑定的值,res也能调用func中的
![image-20221011161834717](https://pic.jitudisk.com/public/2022/10/11/035937e759b88.png)
函数嵌套时,名称空间的绑定关系
4.可以当作容器类型(可以存放多个数据的数据类型:列表、元组、字典、集合)的数据
# 案例6
def index():
print('from index')
l1 = [11, 22, 11.11, 'jason', index]
l1[-1]() # from index
# 通过索引 列表中 的 元素 函数名 去调用函数
# 案例7 通过将函数名保存在字典中,索引函数名 使用函数功能
def register():
print('注册功能')
def login():
print('登录功能')
def withdraw():
print('提现功能')
def transfer():
print('转账功能')
def shopping():
print('购物功能')
# 定义功能编号与功能的对应关系
func_dict = {
'1': register,
'2': login,
'3': withdraw,
'4': transfer,
'5': shopping
}
while True:
print("""
1.注册功能
2.登录功能
3.提现功能
4.转账功能
5.购物功能
""")
choice = input('>>>:').strip()
if choice in func_dict:
func_dict.get(choice)()
else:
print('功能编号不存在')
![image-20221011171930571](https://pic.jitudisk.com/public/2022/10/11/5168a8034e5b5.png)
三、闭包函数
闭包函数:定义在函数内部的函数,并且用到了外部函数空间的名字
也就是函数被当作数据处理的时候,始终以自带的作用域为准,若内嵌函数包含外对外部函数作用域中变量的引用,那么该'内嵌函数'就是闭包函数
''' 满足的要求:
1.定义在函数内部
2.用到了外部函数名称空间的名字(变量名)'''
# 案例1
def index():
print('jason')
def inner():
print(name) # 是变量名而不是数据值
1.闭包函数的实际应用
1.闭包函数是另一种给函数体代码传参的方式
# 函数体传参的方式一:代码里面缺什么变量名就在形参中补充什么变量名
def register(name, age):
print(f'''
name:{name}
age:{age}
''')
# 函数体传参的方式二:闭包函数
def outer():
name = 'jason'
age = 12
def register(name, age):
print(f'''
name:{name}
age:{age}
''')
return register
res = outer()
# 闭包函数特点1:不会受外界变量名的影响
![10.11 插图9.png](https://pic.jitudisk.com/public/2022/10/11/f502f16268f9a.png)
当第5步的x 没有被使用时,会变灰,即pycharm提示当前程序内并没有使用到这个对象,只要在程序内没有其他代码使用它的时候就会变灰来表示没有被引用可以删除不占用资源
# 闭包函数的特点2:绑定一次数据值可以重复使用
def outer(name, age):
def register(name, age):
print(f'''
name:{name}
age:{age}
''')
return register
res = outer('jason', 18)
res()
res()
res = outer('kevin', 38)
res()
res()
res()
![image-20221011184817270](https://pic.jitudisk.com/public/2022/10/11/5724a8896e659.png)
![image-20221011185247791](/Users/duoduo/Library/Application Support/typora-user-images/image-20221011185247791.png)
1.在1次传参后,可以重复使用
2.可以通过改变传进去的参数,对结果进行更改
四、装饰器
1.装饰器简介
1.概念
在不改变被装饰对象原代码和调用方式的情况下,给被装饰对象添加新的功能
"""
软件包含功能的源代码以及调用方式,都应该避免修改,避免出错。
而对于上线后的软件,新需求则意味着扩展的可能性,应该为程序提供扩展的可能性
"""
2.本质
并不是一门新的技术,而是由函数参数、名称空间、函数名多种用法、闭包函数组合到一起的结果
3.装饰器口诀
对修改封闭,对扩展开放
"""
软件的设计应该遵循开放封闭原则,对扩展开放,对修改封闭。对扩展开放意味着有新的需求或者变化时,可以对现有代码进行扩展,以适应新的情况。对修改封闭,意味着对象一旦设计完成,就可以独立完成其工作,而不要对其进行修改。
"""
4.储备知识
时间相关操作
1)时间戳 time.time
import time
print(time.time()) # 时间戳(距离1970-01-01 00:00所经历的秒数)
2)时间阻塞 time.sleep()
import time
time.sleep()
2.装饰器推导流程
# 案例
import time
def index():
time.sleep(3)
print('from index')
def home():
time.sleep(1)
print('from home')
如果想为案例中的代码添加新的功能,该如何实现?
1.直接在调用index函数前后添加新功能的代码
import time
def index():
time.sleep(3)
print('from index')
def home():
time.sleep(1)
print('from home')
start_time = time.time()
index()
end_time = time.time()
print('函数index的执行时间为:', end_time-start_time)
如果想要多次调用index函数如何实现新功能,该如何实现?
2. 建立新功能的函数实现多次调用index函数新功能
相同的代码不同位置反复执行==>>> 函数
定义新功能为函数,即可通过调用函数多次使用新功能
def get_time():
start_time = time.time()
index()
end_time = time.time()
print('函数index的执行时间为:', end_time - start_time)
get_time()
![image-20221011191952414](/Users/duoduo/Library/Application Support/typora-user-images/image-20221011191952414.png)
但是这样函数体代码不够灵活,只能对index函数使用,如何对其他函数使用?
3.使用参数可以传参变换统计的函数
利用参数,将统计的函数名传给参数,变换传参即变化统计的函数
def get_time(v):
start_time = time.time()
v()
end_time = time.time()
print('函数index的执行时间为:', end_time - start_time)
get_time(home)
get_time(index)
---------------res--------------------
from home
函数index的执行时间为: 1.003127098083496
from index
函数index的执行时间为: 3.0050511360168457
如何通过调用函数的方式,去使用新功能?
4.使用闭包函数来调用新功能
通过闭包函数来将调用函数的方便变简便
def outer(v):
def get_time():
start_time = time.time()
v()
end_time = time.time()
print('函数index的执行时间为:', end_time - start_time)
return get_time
res = outer(index)
res()
res = outer(home)
res()
---------------res--------------------
from index
函数index的执行时间为: 3.005207061767578
from home
函数index的执行时间为: 1.004741907119751
如何使用原函数名来调用具有新功能的函数?
5.使用赋值语句使调用原函数名时具有新功能
将原函数名 绑定向 扩展了新功能的函数体代码
def outer(v):
def get_time():
start_time = time.time()
v()
end_time = time.time()
print('函数index的执行时间为:', end_time - start_time)
return get_time
index = outer(index)
index()
home = outer(home)
home()
---------------res--------------------
from index
函数index的执行时间为: 3.005207061767578
from home
函数index的执行时间为: 1.004741907119751
![image-20221011200429696](/Users/duoduo/Library/Application Support/typora-user-images/image-20221011200429696.png)
如果想调用有参函数怎么办?
6.为闭包函数引入参数,兼容有参函数,以及有返回值的函数
---------------res--------------------
from index
函数index的执行时间为: 3.005207061767578
from home
函数index的执行时间为: 1.004741907119751将函数的类型丰富
import time
def index(a):
time.sleep(3)
print('from index',a)
return 'index' #
def outer(res):
def get_time(*args,**kwargs):
start_time = time.time()
res(*args,**kwargs)
end_time = time.time()
print('函数index的执行时间为:', end_time - start_time)
return res
return get_time
index = outer(index)
res = index(1)
print(res)
---------------res--------------------
from index 1
函数index的执行时间为: 3.005103826522827
<function index at 0x1007c9430>
3.装饰器模版
def outer(func):
def inner(*args, **kwargs):
# 执行被装饰对象之前可以做的额外操作
res = func(*args, **kwargs)
# 执行被装饰对象之后可以做的额外操作
return res
return inner
4.装饰器语法糖
用符号@装饰器的函数名,调用该装饰器,且把它正下方的函数名当作是参传入,然后将返回的结果重新赋值给原函数名
def outer(func):
def inner(*args, **kwargs):
# 执行被装饰对象之前可以做的额外操作
res = func(*args, **kwargs)
# 执行被装饰对象之后可以做的额外操作
return res
return inner
"""
语法糖 @装饰器的函数名,调用该装饰器,且把它正下方的函数名当作是参传入,然后将返回的结果重新赋值给原函数名
"""
@outer # func = outer(func)
def func():
print('from func')
return 'func'
aa ```python
aaa
![image-20221011113054290](/Users/duoduo/Library/Application Support/typora-user-images/image-20221011113054290.png)
5
![image-20221011114132492](/Users/duoduo/Library/Application Support/typora-user-images/image-20221011114132492.png)
7
![image-20221011115157515](/Users/duoduo/Library/Application Support/typora-user-images/image-20221011115157515.png)
装饰器模版
装饰器模版糖
标签:index,函数,python,res,之闭,time,print,装饰,def From: https://www.cnblogs.com/DuoDuosg/p/16782495.html