ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[2022.7.5]闭包函数与解释器详细讲解

2022-07-06 00:01:55  阅读:137  来源: 互联网

标签:闭包 解释器 函数 home func time print 2022.7 def


闭包函数与解释器详细讲解

闭包函数简介

闭包函数
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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有