函数和常用模块【day05】:装饰器前奏(一)
本节内容
- 定义
- 原则
- 实现装饰器的储备知识
- 函数及变量
- 高阶函数
一、定义
1、装饰器:本质是函数。
2、功能:用来装饰其他函数,顾名思义就是,为其他的函数添加附件功能的。
二、原则
- 不能修改被装饰函数的源代码
- 不能修改被装饰函数的调用方式
装饰器为什么会有这两个原则呐?因为如果你写的这个程序在生产环境下已经运行了,如果修改别人的源代码或者修改别人的调用方式,那么出了问题,后果可想而知,所以我们要牢记上面两个原则。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
def logging(): print("logging...")#正确写法,没有修改源码def test1(): pass#错误写法,不能修改源码def test1(): pass logging()# 调用方式,也不能被修改test1() |
三、实现装饰器知识储备
- 函数即"变量"
- 高阶函数
- 嵌套函数
最终: 高阶函数+嵌套函数 => 装饰器
四、函数即变量
1、python的内存机制
|
1
2
3
4
5
|
#变量x = 1#函数def test(): pass |
以上一个变量一个函数在内存中的表现形式如下图:

在python解释器中,有一个概念叫做引用基数,那什么叫引用基数呐,就是比方说,x=1,它会先在内存当中把1这个值试试在在的存放下来,这个x其实就是1的门牌号,也是对1的一次引用。python什么时候把这个1这个屋子清空呐?它会等到1所对应的门牌号都没有了,就会把1这里面的东西给清掉,这个也是python的内存回收机制,就是靠这种方式回收的。
2、del清理
那我们用什么清理呐?用del去清理门牌号,就是对1的值引用的变量,del x就表示清理掉1对应的x的门派号。如果x没有被del,则x永远不还被删除,除非程序结束了,不然永远不会被删除。del删除的不是1,只是把门牌号x删除了,只是定期刷新时,发现1没有被其他门牌号引用了,才会被清掉。
3、函数在内存的表现形式
我们先通过三个例子来解释一下:
①bar函数在foo函数之后定义
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
#bar函数在foo函数之后定义def foo(): print("in the foo") bar()def bar(): print("in the bar")foo()#输出in the fooin the bar |
②bar函数是在foo函数之前定义
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
# bar函数是在foo函数之前定义def bar(): print("in the bar")def foo(): print("in the foo") bar()foo()#输出in the fooin the bar |
显然,两种写法效果是一样的,那我们来看看第三种情况。
③bar函数在foo函数调用之后声明
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
# bar函数在foo函数调用之后声明def foo(): print("in the foo") bar()foo()def bar(): print("in the bar")#输出Traceback (most recent call last):in the foo File "D:/PycharmProjects/pyhomework/day4/装饰器/函数即变量.py", line 31, in <module> foo() File "D:/PycharmProjects/pyhomework/day4/装饰器/函数即变量.py", line 29, in foo bar()NameError: name 'bar' is not defined #bar函数没有定义 |
为啥呢?bar函数我不是定义了吗?下面我们就用一个图来解释一下。

从图中不难看出第三种错误是因为在执行foo函数时,当调用bar函数时,bar还函数还定义,所以报错。
五、高阶函数
实现高阶函数有两个条件:
- 把一个函数名当做实参传给另外一个函数
- 返回值中包含函数名
1、把一个函数名当做实参传给另外一个函数
作用:在不修改被装饰函数源代码的情况下为其添加功能
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
def bar(): time.sleep(3) print("in the bar")def test1(func): print(func) start_time = time.time() func() stop_time = time.time() print("the func run the is %s"%(stop_time-start_time))#没有修改bar的代码test1(bar) #把bar函数名当做实参传到test1中#输出<function bar at 0x0000000000A7D378> #bar函数的内存地址in the barthe func run the is 2.9912972450256348 |
2、返回值中包括函数名
作用:不修改函数调用方式
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
import timedef bar(): time.sleep(3) print("in the bar")def test2(func): print(func) return func #返回函数的内存地址#调用test2函数bar = test2(bar) bar() #没有bar函数改变调用方式#输出<function bar at 0x0000000000B6D378> #打印bar函数的内存地址in the bar |
函数和常用模块【day05】:装饰器前奏(一)的更多相关文章
- 小白的Python之路 day4 装饰器前奏
装饰器前奏: 一.定义: 1.装饰器本质是函数,语法都是用def去定义的 (函数的目的:他需要完成特定的功能) 2.装饰器的功能:就是装饰其他函数(就是为其他函数添加附加功能) 二.原则: 1. 不能 ...
- 探究functools模块wraps装饰器的用途
<A Byte of Python>17.8节讲decorator的时候,用到了functools模块中的一个装饰器:wraps.因为之前没有接触过这个装饰器,所以特地研究了一下. 何谓“ ...
- python进阶04 装饰器、描述器、常用内置装饰器
python进阶04 装饰器.描述器.常用内置装饰器 一.装饰器 作用:能够给现有的函数增加功能 如何给一个现有的函数增加执行计数的功能 首先用类来添加新功能 def fun(): #首先我们定义一个 ...
- 为什么 Python 没有函数重载?如何用装饰器实现函数重载?
英文:https://arpitbhayani.me/blogs/function-overloading 作者:arprit 译者:豌豆花下猫("Python猫"公众号作者) 声 ...
- Python初学者第二十三天 函数进阶(2)装饰器
装饰器: 需求----> 写一个功能,测试其他同事函数的调用效率. 第一版:功能版 import time def func(): time.sleep(0.2) print('非常复杂') d ...
- python函数知识七 闭包、装饰器一(入门)、装饰器二(进阶)
21.闭包 闭包:在嵌套函数内,使用非全局变量(且不使用本层变量) 闭包的作用:1.保证数据的安全性(纯洁度).2.装饰器使用 .__closure__判断是否是闭包 def func(): a = ...
- 函数和常用模块【day05】:装饰器高潮(三)
本节内容 1.概述 2.装饰器定义 3.装饰器定义 4.带参数的生成器 一.概述 我们之前介绍了大幅片的内容,感觉跟装饰器半毛钱关系都没有,其实不然,我们分别详细阐述了高阶函数和内置函数,下面我们就来 ...
- Day05:装饰器,三元表达式,函数的递归,匿名/内置函数,迭代器,模块,开发目录
上节课复习:1.函数的对象 函数可以被当作数据取处理2.函数嵌套 嵌套调用:在调用一个函数时,函数体代码又调用了其他函数 嵌套定义:在一个函数内部又定义了另一个函数 def foo( ...
- python函数与模块(装饰器,文件处理,迭代器等)
os模块 os.system('命令') 利用python调用系统命令,命令可以是以列表或者元组内的元素形式* res import os res=os.system('ipconfig') prin ...
随机推荐
- 洛咕 P2336 [SCOI2012]喵星球上的点名
洛咕 P2336 [SCOI2012]喵星球上的点名 先求出SA和height,一个点名串对应的就是一段区间,还有很多个点,就转化成了 有很多个区间,很多个点集,对每个区间计算和多少个点集有交,对每个 ...
- bootstrap-validator基本使用(自定义验证身份证号和手机号)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...
- R绘图 第五篇:绘制散点图(ggplot2)
ggplot2包中绘制点图的函数有两个:geom_point和 geom_dotplot,当使用geom_dotplot绘图时,point的形状是dot,不能改变点的形状,因此,geom_dotplo ...
- Security3: 架构和权限
架构(Schema)是数据库对象(比如,Table,View,存储过程等)的容器,授予用户对Schema访问的权限,就是授予用户对Schema下所有object的访问权限. 一,架构(Schema)是 ...
- 手机Gmail上用Exchange协议配置收发QQ邮箱
1.开启Exchange服务 2.生成授权码(登录密码) 3."服务器"填入ex.qq.com
- Kafka高性能吞吐关键技术分析
Apache Kafka官网提供的性能说明: Benchmarking Apache Kafka: 2 Million Writes Per Second (On Three Cheap Machin ...
- CentOS7安装OpenStack(Rocky版)-01.控制节点的系统环境准备
分享一下Rocky版本的OpenStack安装管理经验: OpenStack每半年左右更新一版,目前是版本是201808月发布的版本-R版(Rocky),目前版本安装方法优化较好,不过依然是比较复杂 ...
- 每日scrum(2)
今天是冲刺的第二天,小组主要做了界面的美化,加入了软件的开始动画,以及学校景点的美图介绍: 主要的问题在于除了开始界面,进入软件之后还是有待改进,功能的呈现有待加强. 任务看板: 燃尽图: 会议照片:
- Android DatePickerDialog和TimePickerDialog显示样式
可以用DatePickerDialog显示选取日期的对话框.可以设置显示的样式 1.通过构造方法设置显示样式. 可以通过DatePickerDialog(Context context, int th ...
- Java之可变参数方法使用说明
代码: package test_demo; /* * 可变参数函数说明 * 传入指定数据类型的数组 * 优先匹配固定长度函数 * */ public class VarArgsDemo { // 可 ...