[2022.7.5]闭包函数与解释器详细讲解
作者:互联网
闭包函数与解释器详细讲解
闭包函数简介
闭包函数
1.定义在函数内部的函数(函数的嵌套)
2.内部函数使用的了外部函数名称空间的名字
"""
只有满足以上两种特征的函数次才可以称为闭包函数
"""
![](https://www.icode9.com/i/l/?n=22&i=blog/2912772/202207/2912772-20220705162945111-1787198664.png)
def func(name):
# name = 'make' 可以省略
def index():
print(name)
return index
res = func('make') # 直接填写参数就可以直接传值
print(res) # <function func.<locals>.index at 0x0208B070>
res() # make
res1 = func('jason')
print(res1) # <function func.<locals>.index at 0x00B68778>
res1() # jason
# 上图是代码执行顺序流程 在 func 函数代码体中的 name = 'make' 可以直接省略 res接收到返回值 就是return 后面的index 等同于 res = index(函数名) 然后在res后面加一个() 就可以直接调用函数了 后续调用 更换实参就可以了
闭包函数的实际应用
"""
实际应用的场景 简单点说就是给函数传参
"""
1.第一种给函数体代码传值的方式:是通过形参给函数传值
def func(name):
print(name)
func('make')
# 调用函数时 必须要对应形参给到一个数据值 通过形参传值才可以调用
2.第二种给函数体代码传值的方式:闭包函数
def func(name):
def index():
print(name)
return index
res = func('make') # 直接填写参数就可以直接传值
res() # make
res1 = func('jason') # # 直接填写参数就可以直接传值
res1() # jason
# 闭包函数中 用res这个变量 接收 return 后面的函数名 index 在实参中填写数据值就可以调用函数了 后续想随意的调用 再用一个新的变量名接收 即可调用函数
装饰器简介
1.装饰器的本质
器:代表函数的意思。装饰器本质就是在不改变被装饰对象的 '调用方法'和'内部代码'的情况下给其添加附加功能
被装饰函数感受不到装饰器的存在
2.装饰器的原则
不能修改被装饰的函数的代码体结构
不能修改被装饰的函数的调用方式
(对修改说no 对扩展yes)
3.知识储备
import time
print(time.time()) # 1657019688.9723196
'''
上述为时间戳(单位:秒):此刻 距离 1970年1月1日0时0分0秒 所经历的秒速
'''
可以用此测算出代码运行多长时间结束
import time
start_time = time.time()
for i in range(999):
print(i)
end_time = time.time()
time1 = end_time - start_time
print(time1) # 0.004122018814086914
# 此代码运行时间为0.004122018814086914 秒
time.sleep() # 括号里写x秒 就可以让改代码延迟x秒出结果
例如:
time.sleep(10)
print(999) # 会等待10秒后 才出结果
装饰器前期推导
1.
import time
def func():
time.sleep(5) # 延迟5秒出结果
print('from func')
'统计下函数func中执代码执行的时间'
start_time = time.time() # 启动时间
func() # from func
end_time = time.time() # 结束时间
print(end_time-start_time) # 5.004950761795044 代码运行时间
"""
此代码缺陷:
如果需要多次调用函数 需要重复的编写代码
比较繁琐
故可以把此代码封装成函数
"""
2.
import time
def func():
time.sleep(5) # 延迟5秒出结果
print('from func')
'统计下函数func中执代码执行的时间'
def time1():
start_time = time.time() # 启动时间
func() # from func
end_time = time.time() # 结束时间
print(end_time-start_time) # 代码运行时间
time1() # 5.013692855834961
time1() # 5.0031561851501465
time1() # 5.004458427429199
"""
封装成函数后虽然可以多次调用 但是每次调用的都是函数func的值 如果有多个不同函数需要统计代码运行时间 此代码措施不能兼备
故
给函数体添加形参(动态传参)
"""
3.
import time
def foo():
time.sleep(3)
print('from foo')
def func():
time.sleep(5)
print('from func')
def time1(unknown):
start_time = time.time()
unknown()
# unknown(*args,**kwargs)
end_time = time.time()
print(end_time-start_time)
time1(foo)
time1(func)
"""
看似好像只要在前定义好函数 后面就可以随意调用函数 获取运行时间 其实我们刚才定义的函数都是没有形参的
代码体中的函数名 unknown() 这个括号里面是固定没有参数的
def func1(a):
time.sleep(3)
print('from func1')
get_time(func1) # 报错
如果在定义函数的时候 写了形参 上述代码
调用时就会报错
因为代码体里的 unknown() 前面的函数名可以随意的更改 但是()已经写死了 固定是不可以写入参数的 不过也可以解决
措施:
可以在括号里写入 可变长参数 (*args,**kwargs) 但是目前这种代码结构不支持这样写入(暂且忽略)
还有一点:
上面的调用方式已经改变了 被装饰的函数的调用方式 违背装饰器的原则
解决措施:
装饰器推导流程
"""
装饰器的各种版本
"""前面讲到 传入的函数一旦填写了参数 代码运行起来就会报错 用(*args,**kwargs)上述结构无法运行也会报错
"""
"""
下面介绍解决措施 针对有参无参函数如何兼容
"""
2.无参函数调用方式
import time
def foo(unknown):
def time1():
start_time = time.time()
unknown()
end_time = time.time()
print(end_time-start_time)
return time1
def home():
time.sleep(3)
print('from home')
home = foo(home)
home()
def index():
time.sleep(4)
print('from index')
index = foo(index)
index()
2.有参函数调用方式
# import time
# def foo(unknown):
# def time1(*args, **kwargs):
# start_time = time.time()
# unknown(*args, **kwargs)
# end_time = time.time()
# print(end_time-start_time)
# return time1
# def func(name = 'jason',age = 18):
# time.sleep(4)
# print(name, age)
# func = foo(func)
# func()
# def home(a,b):
# time.sleep(3)
# print('from home')
# home = foo(home)
# home(0, 0)
# def index(name):
# time.sleep(4)
# print(name)
# index = foo(index)
# index('make')
3.装饰器的完整版
import time
def foo(unknown):
def time1(*args, **kwargs):
start_time = time.time()
res = unknown(*args, **kwargs)
end_time = time.time()
print(end_time-start_time)
return res
return time1
def func(name = 'jason',age = 18):
time.sleep(4)
print(name, age)
return '执行func函数的返回值'
func = foo(func)
res = func()
print(res)
def home(a,b):
time.sleep(3)
print('from home')
return '执行home函数的返回值'
home = foo(home)
res = home(1,2)
print(res)
装饰器模板
import time
def foo(unknown):
def time1(*args, **kwargs):
start_time = time.time()
res = unknown(*args, **kwargs)
end_time = time.time()
print(end_time-start_time)
return res
return time1
def func(name = 'jason',age = 18):
time.sleep(4)
print(name, age)
return '执行func函数的返回值'
func = foo(func)
res = func()
print(res)
def home(a,b):
time.sleep(3)
print('from home')
return '执行home函数的返回值'
home = foo(home)
res = home(1,2)
print(res)
装饰器的固定模板
from functools import wraps
def outer(func_name):
@wraps(func_name) # 仅仅是为了让装饰器不容易被别人发现 做到真正的以假乱真
def inner(*args, **kwargs):
print('执行被装饰对象之前可以做的额外操作')
res = func_name(*args, **kwargs)
print('执行被装饰对象之后可以做的额外操作')
return res
return inner
# import time
# def home():
# time.sleep(1)
# print('from home')
# return 'home返回值'
# home = outer(home)
# res = home()
# print(res)
"""
执行home函数之前需要添加校验用户身份的功能
"""
# 装饰器语法糖
import time
@outer # home = outer(真正的函数名home)
def home():
'''我是home函数 我要热死了!!!'''
time.sleep(1)
print('from home')
return 'home返回值'
# help(home)
# print(home)
home()
# def index():
# '我是index函数 我的功能很强大'
# pass
#
# help(index)
标签:闭包,解释器,函数,home,func,time,print,2022.7,def 来源: https://www.cnblogs.com/55wym/p/16449130.html