装饰器是什么

用来修饰别的函数的函数就可以称之为装饰器

这种函数的参数一般就是另外一个函数

也就是说,调用这种函数,需要给这种函数传参,且参数是函数

@语法糖

@语法糖一般用来表示装饰器函数

不用@也可以达到装饰函数的目的,下面会有演示

函数嵌套

在一个函数中定义另外一个函数

def f1(arg="aaa"):
def f2():
return "hello"
def f3():
return "hi"
def f4():
return "haha" print f2()
print f3()
print f4()

这个f1函数有默认参数,所以可以不传参执行

执行f1()调用之后

执行结果如下:

hello

hi

haha

在函数里返回函数
def hi(arg="aaa"):
def greet():
return "bbb" def welcome():
return "ccc" if arg == "aaa":
return greet
else:
return welcome a = hi()
print(a)
print (a())

这里同样使用了默认参数,则a = hi() 会命中 if arg == "aaa"这个逻辑

返回greet,注意在这里,greet是函数,不是字符串,如果是返回字符串,则要返回的是 return "greet"这种

上面这段代码执行的结果是

<function greet at 0x7f75f7a0e1b8>

bbb

为什么是这样的执行结果呢?第一个地方 print(a),打印的是a = hi()的结果

我们可以看到,hi()的返回结果都是在return一个函数,要么是greet函数,要么是welcome函数

函数就是对应一个地址,所以第一处打印的是这个函数的地址

第二处做了a的调用,即a(),则打印返回的函数即greet函数执行的结果,即bbb

将函数作为参数传给另外一个函数
def hi():
return "hi" def hello(func):
print("before func()")
print(func()) hello(hi)

执行结果是

before func()

hi

这里把hi这个函数作为参数传给hello函数

hello函数先打印一句自身的输出before func()

再执行这个被传入的函数

我们可以看到,通过装饰器,我们可以在一个函数被调用前干一些需要的事情

不用@实现装饰器
def hi(a_func):

    def hello():
print("I am doing some boring work before executing a_func()") a_func() print("I am doing some boring work after executing a_func()")
return hello def haha():
print("I am the function which needs some decoration ") haha = hi(haha)
print haha()

运行结果:

I am doing some boring work before executing a_func()

I am the function which needs some decoration

I am doing some boring work after executing a_func()

None

这个就是装饰器,起到了用hi函数装饰了haha函数的功能

那么怎么用@语法糖实现呢
def hi(a_func):

    def hello():
print("I am doing some boring work before executing a_func()") a_func() print("I am doing some boring work after executing a_func()")
return hello @hi
def haha():
print("I am the function which needs some decoration ") haha()

可以看到,装饰器就是用希望装饰别的函数的函数,比如 ,希望用A装饰B

就在定义B函数的上一行,写上 @A

def A():
pass @A
def B():
pass

总结:理解就是装饰器其实就是这样一种函数:带参数的,且参数是另外一个函数的函数

使用装饰器的目的一般是为了在运行时改变函数的一些属性/行为,就可以给这个函数加上装饰器,让装饰器去在这个函数被调用前后,干一些你想做的事情

wraps干什么的?

我们修改下上面的代码,多记录一点东西

def hi(a_func):

    def hello():
print("I am doing some boring work before executing a_func()") a_func() print("I am doing some boring work after executing a_func()")
return hello @hi
def haha():
print("I am the function which needs some decoration ") haha()
print(haha.__name__)

我们的意图是打印haha这个函数的函数名,但实际上打印的是hello

为什么?

因为haha这个函数使用装饰器之后,haha的行为部分被装饰器函数改变了

可以看到,用hi函数装饰了haha之后,返回的是hello函数,那么当我们需要拿到被装饰函数的函数名,还有其他属性的时候怎么做呢?

使用functools.wraps方法

from functools import wraps
def hi(a_func):
@wraps(a_func)
def hello():
print("I am doing some boring work before executing a_func()") a_func() print("I am doing some boring work after executing a_func()")
return hello @hi
def haha():
print("I am the function which needs some decoration ") haha()
print(haha.__name__)

执行结果如下:

I am doing some boring work before executing a_func()

I am the function which needs some decoration

I am doing some boring work after executing a_func()

haha

正是我们想要的结果

@wraps接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等的功能。这可以让我们在装饰器里面访问在装饰之前的函数的属性。

举一个记录日志的例子
from functools import wraps

def logit(func):
@wraps(func)
def with_logging(*args, **kwargs):
print(func.__name__ + " was called")
return func(*args, **kwargs)
return with_logging @logit
def addition_func(x):
"""Do some math."""
return x + x result = addition_func(4)
# Output: addition_func was called

python-装饰器简述的更多相关文章

  1. 关于python装饰器

    关于python装饰器,不是系统的介绍,只是说一下某些问题 1 首先了解变量作用于非常重要 2 其次要了解闭包 def logger(func): def inner(*args, **kwargs) ...

  2. python装饰器通俗易懂的解释!

    1.python装饰器 刚刚接触python的装饰器,简直懵逼了,直接不懂什么意思啊有木有,自己都忘了走了多少遍Debug,查了多少遍资料,猜有点点开始明白了.总结了一下解释得比较好的,通俗易懂的来说 ...

  3. Python 装饰器学习

    Python装饰器学习(九步入门)   这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方式. 第一步:最简单的函数,准备附加额外功能 1 2 3 4 5 6 7 8 # -*- c ...

  4. python 装饰器修改调整函数参数

    简单记录一下利用python装饰器来调整函数的方法.现在有个需求:参数line范围为1-16,要求把9-16的范围转化为1-8,即9对应1,10对应2,...,16对应8. 下面是例子: def fo ...

  5. python 装饰器学习(decorator)

    最近看到有个装饰器的例子,没看懂, #!/usr/bin/python class decorator(object): def __init__(self,f): print "initi ...

  6. Python装饰器详解

    python中的装饰器是一个用得非常多的东西,我们可以把一些特定的方法.通用的方法写成一个个装饰器,这就为调用这些方法提供一个非常大的便利,如此提高我们代码的可读性以及简洁性,以及可扩展性. 在学习p ...

  7. 关于python装饰器(Decorators)最底层理解的一句话

    一个decorator只是一个带有一个函数作为参数并返回一个替换函数的闭包. http://www.xxx.com/html/2016/pythonhexinbiancheng_0718/1044.h ...

  8. Python装饰器由浅入深

    装饰器的功能在很多语言中都有,名字也不尽相同,其实它体现的是一种设计模式,强调的是开放封闭原则,更多的用于后期功能升级而不是编写新的代码.装饰器不光能装饰函数,也能装饰其他的对象,比如类,但通常,我们 ...

  9. Python装饰器与面向切面编程

    今天来讨论一下装饰器.装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数 ...

  10. python装饰器方法

    前几天向几位新同事介绍项目,被问起了@login_required的实现,我说这是django框架提供的装饰器方法,验证用户是否登录,只要这样用就行了,因为自己不熟,并没有做过多解释. 今天查看dja ...

随机推荐

  1. 论文笔记(8):BING: Binarized Normed Gradients for Objectness Estimation at 300fps

    译文: <基于二值化赋范梯度特征的一般对象估计> 摘要: 通过训练通用的对象估计方法来产生一组候选对象窗口,能够加速传统的滑动窗口对象检测方法.我们观察到一般对象都会有定义完好的封闭轮廓, ...

  2. python迭代和切片

    from collections import Iterable #切片************************ # #取一个list或tuple的部分元素是非常常见的操作 ,Python提供 ...

  3. BaaS 的由来(1)

    百度百科是这么定义的, BaaS(后端即服务:Backend as a Service)公司为移动应用开发者提供整合云后端的边界服务.其实不仅是移动应用,现在更多的PC应用也同样适用移动端的标准. 在 ...

  4. PHP+MySQL分页原理实现

    功能简介:包含上一页.下一页.首页.尾页.跳转页面等功能. 编码寄语:化繁为简,则豁然开朗. 运行截图: 关键步骤: 创建数据库 CREATE TABLE `page` ( `ID` ) NOT NU ...

  5. WPF自学入门(九)WPF自定义窗口基类

    今天简单记录一个知识点:WPF自定义窗口基类,常用winform的人知道,winform的窗体继承是很好用的,写一个基础窗体,直接在后台代码改写继承窗体名.但如果是WPF要继承窗体,我个人感觉没有理解 ...

  6. ubuntu下ftp服务

    (1).首先用命令检查是否安装了vsftpd vsftpd -version 如果未安装用一下命令安装 sudo apt-get install vsftpd 安装完成后,再次输入vsftpd -ve ...

  7. VMware静态地址上网

    虚拟机通过dhcp获取ip,当系统重启时可能导致ip变更,出现不必要的麻烦,以下是通过nat模式设置虚拟机静态ip同时能够上网的方式. 编辑VMware,依次点击“编辑”--“虚拟网络编辑器” 注:为 ...

  8. C语言第八次博客作业--字符数组

    一.PTA实验作业 题目1:查验身份证 1. 本题PTA提交列表 2. 设计思路 定义i,flag=1,z,m[11],a[19] 输入次数n for i=1 to n+1 gets(a) 加权求和在 ...

  9. [SCOI2010] 连续攻击问题

    题目 Description lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示.当他使用某种装备时,他只能使用该装备的某一 ...

  10. 走近webpack(2)--css打包及压缩js

    前面的文章介绍了webpack的devServer以及多入口多出口文件的配置,咱们继续往下学. 在开始学习接下来的知识之前,我们先回顾一下,前文提到了webpack的简单配置方法,但是只详细说了下入口 ...