函数 装饰器 python
今日内容概要
1.闭包函数
2.闭包函数的实际应用
3.装饰器简介(重点加难点)
4.简易版本装饰器
5.进阶版本装饰器
6.完整版本装饰器
7.装饰器模板(拷贝使用即可)
8.装饰器语法糖
9.装饰器修复技术
今日内容详细
闭包函数(重要)
# 闭包函数的两大特征
1.闭:定义在函数内部的函数
2.包:内部函数使用了外层函数名称空间中的名字
def outer():
a = 999
def inner():
print('from outer>>>inner',a)
return inner
a = 888
res = outer()
res()
闭包函数实际应用
# 闭包函数是给函数体传参的另外一种方式
# 函数体传参的方式
1. 形参
def index(user_name):
print(user_name)
# 函数体代码需要什么就可以在形参中写什么
index('zhou')
2.闭包
def outer():
user_name = 'zhou'
def index():
print(user_name) # 永远使用的都是zhou
return index
res = outer()
def outer(user_name):
# user_name = 'zhou'
def index():
print(user_name) # 永远使用的都是zhou
return index
res = outer('chen') # 形参user_name与值chen临时绑定>>>:outer局部名称空间中
res()
res1 = outer('zhou') # 形参user_name与值zhou临时绑定>>>:outer局部名称空间中
res1()
装饰器简介
"""
装饰器并不是一个新的知识点 而是由前两天所有的函数知识点整合到一起的产物
名称空间 函数名 闭包函数...
"""
装饰器的本质
在不改变被装饰对象原有的‘调用方式’和‘内部代码’的情况下给被装饰对象添加新的功能 装饰器的原则: 对扩展开放 对修改封闭
import time
# print(time.time()) # 1647568920.168808
'''上述的数字是时间戳:1970年1月1日0时0分0秒距离刚刚代码运行间隔的秒数'''
# time.sleep(3)
# print('hello world')
# 需求:统一函数的执行时间
import time
def index():
time.sleep(3)
print('from index')
'''给index函数增加了一个统计执行时间的功能'''
start_time = time.time() # 函数执行之前获取一个时间戳
index()
end_time = time.time() # 函数执行之后获取一个时间戳
print(end_time - start_time) # 两个时间戳的差值就是函数的执行时间
简易版本装饰器
import time
def index():
time.sleep(1)
print('from index')
'''给index函数增加了一个统计执行时间的功能'''
start_time = time.time() # 函数执行之前获取一个时间戳
index()
end_time = time.time() # 函数执行之后获取一个时间戳
print(end_time - start_time) # 两个时间戳的差值就是函数的执行时间
思考:如果在很多地方都需要调用index,如何统计index执行时间
>>> 在很多地方都需要执行统计index函数执行时间的代码
>>> 在不同的地方需要执行相同的代码
>>> 函数 直接通过传参的方式
缺陷1:
代码写死了 无法统计其他函数的执行时间
能否解决?
可以 将函数名通过形参的形式传入
缺陷2:
封装成函数之后 调用方式改变了 不符合装饰器原则
能否解决?
不可以 def get_time(func):
start_time = time.time() # 函数执行之后获取一个时间戳
func()
end_time = time.time() # 函数执行之后获取一个时间戳
print(end_time - start_time) # 两个时间戳的差值就是函数的执行时间
def home():
time.sleep(3)
print('from home')
get_time(index)
get_time(home)
'''
第一种直接给函数体传参的方式无法实现装饰器
只能采用第二种给函数体传参的方式试试看了
'''
import time
def index():
time.sleep(1)
print('from index')
def home():
time.sleep(3)
print('from home')
print(home)
def outer(func): # 真正的index被outer局部名称空间存储了
def get_time():
start_time = time.time() # 函数执行之前获取一个时间戳
func() # 调用了真正的index函数
end_time = time.time() # 函数执行之后获取一个时间戳
print(end_time - start_time) # 两个时间戳的差值就是函数的执行时间
return get_time
res = outer(index) # 左侧的res就是一个普通的变量名
res()
a = outer(index) # 左侧的a就是一个普通的变量名
a()
b = outer(index) # 左侧的b就是一个普通的变量名
b()
index = outer(index)
index() # 看似调用的是index 其实调用的谁是get_time
print(index) # 全局名称空间中的index指向的是get_time函数体代码
home = outer(home) # 狸猫换太子
进阶版本装饰器
# 解决的是参数问题
def outer(func_name):
def get_time(*args,**kwargs):
start_time = time.time()
res = func_name(*args,**kwargs) # 执行真正的index函数
end_time = time.time()
print(end_time - start_time)
# return '不要急躁' # 如何在此处返回真正index函数的返回值
return res
return get_time
装饰器模板(重要)
'''编写装饰器其实有一套固定的代码 不需要做任何理解'''
def outer(func_name): # func_name用于接收装饰的对象(函数)
def inner(*args,**kwargs):
print('执行被装饰函数之前 可以做的额外操作')
res = func_name(*args,**kwargs) # 执行真正的被装饰函数
print('执行被装饰函数之后 可以做的额外操作')
return res # 返回真正函数的返回值
return inner
装饰器语法糖
# 仅仅是让代码编写的更加好看,简洁
def outer(func_time):
def inner(*args,**kwargs):
print('执行函数之前的操作')
res = func_name(*args,**kwargs)
# 额外操作
return res
return inner
@outer # 等价于 index = outer(index)
def index(*args,**kwargs):
print('from index')
index = outer(index) # 总感觉这一行代码有点low
@outer # 等价于 home = outer(home)
def home(*args,**kwargs):
print('from home') print(index)
print(home)
'''
语法糖内部原理
1.使用的时候最好紧跟在被装饰对象的上方
2.语法糖会自动将下面紧挨着的函数名传给@后面的函数调用 '''
装饰器修复技术
from functools import warps
def outer(func_name):
@warps(func_name)
def inner(*args,**kwargs):
print('执行被装饰对象之前可以做的操作')
res = func_name(*args,**kwargs)
return res
return inner
@outer
def index():
print('from index')
@outer
def home():
'''这是home函数的注释'''
print('from home')
home()
index()
最终整理的装饰器模板
# 简易版装饰器
def outer(func_name): # 1. 定义外部函数
def inner(): # 3.定义内部函数
start_time = time.time() # 7. 获取函数运行前的时间戳
func_name() # 8. 调用函数,内部函数调用外部函数绑定的形参,由于第2步形参传值,func_name与index临时绑定到一起,且这里是先调用outer函数再赋值,所以func_name绑定的是上面的函数名index,即调用函数index()
end_time = time.time() # 9. 获取函数运行后的时间戳
print(end_time - start_time) # 输出函数运行前后时间戳的差值
return inner # 4. 把内部函数的函数名返回出去
index = outer(index) # 2. 调用外部函数 # 5. 定义变量名index,让index指向outer的返回值
index() # 6. 调用函数,由于index指向inner,所以index()等价于inner(),即调用函数inner()
函数 装饰器 python的更多相关文章
- Python中利用函数装饰器实现备忘功能
Python中利用函数装饰器实现备忘功能 这篇文章主要介绍了Python中利用函数装饰器实现备忘功能,同时还降到了利用装饰器来检查函数的递归.确保参数传递的正确,需要的朋友可以参考下 " ...
- 【Python 函数对象 命名空间与作用域 闭包函数 装饰器 迭代器 内置函数】
一.函数对象 函数(Function)作为程序语言中不可或缺的一部分,但函数作为第一类对象(First-Class Object)却是 Python 函数的一大特性. 那到底什么是第一类对象(Firs ...
- python基础—函数装饰器
python基础-函数装饰器 1.什么是装饰器 装饰器本质上是一个python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能. 装饰器的返回值是也是一个函数对象. 装饰器经常用于有切 ...
- python 修改的函数装饰器
把好的代码记录下来 方便以后学习 修改的函数参数装饰器 from functools import wraps import time import logging def warn(timeout) ...
- python装饰器1:函数装饰器详解
装饰器1:函数装饰器 装饰器2:类装饰器 装饰器3:进阶 先混个眼熟 谁可以作为装饰器(可以将谁编写成装饰器): 函数 方法 实现了__call__的可调用类 装饰器可以去装饰谁(谁可以被装饰): 函 ...
- python学习日记(函数--装饰器)
楔子 前提,我有一段代码(一个函数). import time def run_time(): time.sleep(0.1) print('我曾踏足山巅') 需求1:现在,我想计算这段代码的运行时间 ...
- python基础-----函数/装饰器
函数 在Python中,定义一个函数要使用def语句,依次写出函数名.括号.括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回. 函数的优点之一是,可以将代码块与主程 ...
- Python 函数装饰器
首次接触到装饰器的概念,太菜啦! Python 装饰器可以大大节省代码的编写量,提升代码的重复使用率.函数装饰器其本质也是一个函数,我们可以把它理解为函数中定义了一个子函数. 例如我们有这么一个需求, ...
- python二 总结--函数-- 装饰器
装饰器是什么? 有什么用? 为什么要用? 真的有用吗? 1.装饰器: 装饰器: 定义:本质是函数,(装饰其他函数)就是为其他函数添加附加功能. 原则:1.不能修改被装饰的函数的源代码 ...
随机推荐
- 空间插值生物X适宜性分析
1 前言 这期博主将根据示例大概讲一下插值分析. 2 问题阐述 根据要求,完成以下操作: (1)请就以上条件确定此地区适合X的生活范围,并制作专题图.专题图内容要求以地形和水系作为背景,且给出适宜区域 ...
- Linux上后台保持Terminal交互运行的三种方式:nohub、screen和tmux
镜像下载.域名解析.时间同步请点击 阿里云开源镜像站 后台运行 Linux上,如果一个进程需要保持后台运行,尤其是在Linux服务器上,后台运行程序.避免因为SSH连接断开而导致进程停止运行时,该怎么 ...
- 使用虚拟机在CentOS上安装部署数据库使用
镜像下载.域名解析.时间同步请点击 阿里云开源镜像站 本节描述使用数据库的基本操作.通过此节您可以完成创建数据库.创建表及向表中插入数据和查询表中数据等操作. 2.1 前提条件 ●openGauss正 ...
- 模型 _meta API ( options )
模型 _meta API class Options[源代码] 模型 _meta API是Django ORM的核心.它使系统的其他部分(如查找,查询,表单和管理员)能够了解每个模型的功能. API可 ...
- 编写 Shell 程序,实现自动删除 50 个账号的功能,账号名为stud1 至 stud50 ?
#!/bin/bashfor((i=1;i<51;i++))do userdel -r stud$idone
- MySQL 里记录货币用什么字段类型好?
NUMERIC 和 DECIMAL 类型被 MySQL 实现为同样的类型,这在 SQL92 标准允 许.他们被用于保存值,该值的准确精度是极其重要的值,例如与金钱有关的数 据.当声明一个类是这些类型之 ...
- flash的TotalFrames显示undefined
通过js来操作flash的时候,获取到总帧数的是属性.TotalFrames,而不是属性TotalFrames().在asp.net中,js放在最后可以在一定程度上避免当前flash没有加载完,导致获 ...
- springboot-mail发邮件,不需要邮件服务器
很简单 步骤走起-> 1.需要一个邮箱账号,我以163邮箱为例,先开启第三方服务后获得密码,后面用来邮箱登录 2.加入mail 依赖 3.properties配置账号和第三方服务密码(不是邮箱密 ...
- Linux 安装jdk1.8
Linux安装jdk1.8 总结一句话就是:下载jdk1.8 ==> 解压 ==> 配置环境变量. 一. jdk的下载,这里有两种方法: 1.去Oracle官网下载. 2.jdk1.8的 ...
- 遇到的错误之“Cannot find module 'XXX’的错误”
一.问题: 在进行webpack打包的时候,会出现Cannot find module 'XXX'的错误,找不到某个模块的错误 二.解决方法: (1)方法1: 直接进行npm install重新打包: ...