看了海峰老师讲解的装饰器视频,讲解的非常棒。根据视频,记录笔记如下:

装饰器:

1、本质是函数,用def来定义。功能就是用来(装饰)其他函数,为其他函数添加附加功能

现有两个函数如下,

 def test1():
pass def test2()
pass test1()
test2()

需要添加一个记录日志的功能

原始方法,在每个函数里添加

  def test1():
pass
print('logging') def test2()
pass
print('logging') test1()
test2()

再进一步,增加一个函数,test1和test2来调用

 1 def logger():
2 print('logging')
3
4 def test1():
5 pass
6 logger()
7
8 def test2()
9 pass
10 logger()
11
12 test1()
13 test2()

那假如有上百上千个函数,并且是正常在线的代码,也这样处理吗?很显然这是不可能的

因此装饰器的原则

2、a. 不能修改被装饰的函数的源代码

b.不能修改被装饰的函数的调用方式

实现装饰器知识储备:

3、a. 函数即“变量”

b. 高阶函数

c.嵌套函数

高阶函数+嵌套函数==装饰器

============================================

再来看一下以下几个场景

场景一

 def bar():
print("in the bar") def foo():
print ("in the foo")
bar() foo()

场景二

 def foo():
print ("in the foo")
bar() def bar():
print("in the bar") foo()

场景一和场景二的不同之处在于,一个bar()在foo()之前,一个在foo()之后,但两者结果一样,按理说python应该是从上往下一行一行执行,为啥场景二也没有问题呢

经过断点debug调试,发现在debug的过程中,程序会先把函数都过一遍,顺序是   def  foo()  ---->  def bar()  ---->  foo()  ----> print ("in the foo")   ---> bar() -----> print (in the bar)

那再看场景三

 def foo():
print ("in the foo")
bar() foo() def bar():
print("in the bar")

按照之前的解释,程序也会先把函数都过一遍,然后去执行。但场景三确报错了,会提示 name 'bar' is not defined,debug显示 def foo() 后直接到 foo(), 就直接执行foo()函数了,并没有往下走。

因为遇到foo(),就表示要去执行foo函数,而此时 bar并未在内存建立‘’门牌号‘’,因此会报错

看下面这张图,函数相当于变量的集合。

高阶函数:

a:把一个函数名当做实参传给另外一个函数

(在不修改被装饰函数源代码的情况下为其添加功能)

b:返回值中包含函数名(不修改函数的调用方式),一定要有return,返回该函数的内存地址

如下面的代码

 import time
def bar():
time.sleep(3)
print('in the bar') def test1(func):
start_time = time.time()
func()
stop_time = time.time()
print("the func run time is %s" %(stop_time-start_time)) test1(bar)

此时相当于   func=bar, func()  会执行bar函数

执行结果

in the bar
the func run time is 3.0004918575286865

返回值包含函数名,如

 import time
def bar():
time.sleep(3)
print('in the bar') def test2(func):
print(func)
return func test2(bar)
print("================")
print(test2(bar))

结果

<function bar at 0x000001B343BF3EA0>
================
<function bar at 0x000001B343BF3EA0>
<function bar at 0x000001B343BF3EA0>

print(test2(bar))先打印 func,然后返回func的内存地址。于是又打印一遍

换一种方式

 import time
def bar():
time.sleep(3)
print('in the bar') def test2(func):
print(func)
return func t=test2(bar)
print("================")
# print(test2(bar))
t()

此时会去执行bar函数

结果

<function bar at 0x00000246AECB3EA0>
================
in the bar

那把 t  换成  bar 呢

 import time
def bar():
time.sleep(3)
print('in the bar') def test2(func):
print(func)
return func bar=test2(bar)
print("================")
# print(test2(bar))
bar()

结果和上面是一样的。可以看出函数的调用方式没有改变,结果是一样的

因此引出了装饰器

 import time
def test2(func):
# print(func)
print("auth---")
return func @test2
def bar():
time.sleep(1)
print('in the bar')
bar()

执行结果:

auth---
in the bar

在 in  the  bar 前面加了一段auth---,没有改变bar()的代码

这样装饰器就解释明白了

当然还有多层嵌套和装饰,带参数的装饰器,以后需要加强练习再补充。

学以致用三十六-----弄懂python装饰器的更多相关文章

  1. 利用世界杯,读懂 Python 装饰器

    Python 装饰器是在面试过程高频被问到的问题,装饰器也是一个非常好用的特性, 熟练掌握装饰器会让你的编程思路更加宽广,程序也更加 pythonic. 今天就结合最近的世界杯带大家理解下装饰器. 德 ...

  2. 一篇文章搞懂Python装饰器所有用法

    01. 装饰器语法糖 如果你接触 Python 有一段时间了的话,想必你对 @ 符号一定不陌生了,没错 @ 符号就是装饰器的语法糖. 它放在一个函数开始定义的地方,它就像一顶帽子一样戴在这个函数的头上 ...

  3. Unity3D学习笔记(三十六):Shader着色器(3)- 光照

    光照模型:用数学的方法模拟现实世界中的光照效果.   场景中模型身上的光反射到相机中的光线: 1.漫反射:产生明暗效果 2.高光反射:产生镜面反射,物体中有最亮且比较耀眼的一部分 3.自发光: 4.环 ...

  4. 一篇关于Python装饰器的博文

    这是一篇关于python装饰器的博文 在学习python的过程中处处受阻,之前的学习中Python的装饰器学习了好几遍也没能真正的弄懂.这一次抓住视频猛啃了一波,就连python大佬讲解装饰器起来也需 ...

  5. 第三百六十六节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)的bool组合查询

    第三百六十六节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)的bool组合查询 bool查询说明 filter:[],字段的过滤,不参与打分must:[] ...

  6. 第三百五十六节,Python分布式爬虫打造搜索引擎Scrapy精讲—scrapy分布式爬虫要点

    第三百五十六节,Python分布式爬虫打造搜索引擎Scrapy精讲—scrapy分布式爬虫要点 1.分布式爬虫原理 2.分布式爬虫优点 3.分布式爬虫需要解决的问题

  7. 第三百四十六节,Python分布式爬虫打造搜索引擎Scrapy精讲—Requests请求和Response响应介绍

    第三百四十六节,Python分布式爬虫打造搜索引擎Scrapy精讲—Requests请求和Response响应介绍 Requests请求 Requests请求就是我们在爬虫文件写的Requests() ...

  8. 第三百三十六节,web爬虫讲解2—urllib库中使用xpath表达式—BeautifulSoup基础

    第三百三十六节,web爬虫讲解2—urllib库中使用xpath表达式—BeautifulSoup基础 在urllib中,我们一样可以使用xpath表达式进行信息提取,此时,你需要首先安装lxml模块 ...

  9. 剑指Offer(三十六):两个链表的第一个公共结点

    剑指Offer(三十六):两个链表的第一个公共结点 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.ne ...

随机推荐

  1. python学习Day6 元组、字典、集合set三类数据用法、深浅拷贝

    一.深浅拷贝 1.  值拷贝 ls1 = ls2  不开辟空间,指针跟着走.(直接将ls1中存放的地址拿过来,内存中不会开辟新的空间,所以你怎么变,我也跟着变.)(ls1内部的所有类型的值发生改变,l ...

  2. angular.min.js:118 Error: [ng:areq] http://errors.angularjs.org/1.5.8/ng/areq?

    1,错误如图所示 简单说下错误原因是:没有js没有注册进去. 解决方法: 1.看下index.html有没有引入你的js文件. 2.看下app.js有没有注册js,比如我这次就是这步没做好,合并代码时 ...

  3. python bmp转jpg 且灰度图转彩色

    今天在简书,上看到了一个 bmp转jpg的代码,便记录一下. # coding:utf-8 import os from PIL import Image # bmp 转换为jpg,灰度图转RGB d ...

  4. 常用vi命令

    i  在当前光标处插入字符,并进入编辑模式 o 在当前光标插入下一行 x 从当前光标处向后删除一个字符. dd 删除当前光标处所在行 :q! 强制退出不保存 :q 退出(文本有改动则警告) :w 保存 ...

  5. coderwarrior 查看程序大小 Code Size

    https://mcuoneclipse.com/2012/09/24/code-size-information-with-gcc-for-armkinetis/

  6. tensorflow实现二分类

    读万卷书,不如行万里路.之前看了不少机器学习方面的书籍,但是实战很少.这次因为项目接触到tensorflow,用一个最简单的深层神经网络实现分类和回归任务. 首先说分类任务,分类任务的两个思路: 如果 ...

  7. promise之我见

    在我们平时的方法中有很多方法是promise封装的, 有些函数后边跟的then和catch 就是promise的方法,先看一下pormise的特点 (1)对象的状态不受外界影响.Promise对象代表 ...

  8. xp密钥-资源分享

    xp-密钥:QC986-27D34-6M3TY-JJXP9-TBGMD ftp-资源地址: ftp://10.10.31.2/?tdsourcetag=s_pctim_aiomsg

  9. ARM汇编指令格式

    一.ARM介绍 1) arm汇编中,程序下一步执行哪一条指令,是根据程序计数器(PC)的值来决定. 类比于8086的CS:IP的功能. 2) 8086属于CISC(复杂指令集),每条指令长度不等,ar ...

  10. nohup python 没有print输出

    nohup python -u crake.py >run.log 2>&1  &