装饰器

  首先,给出装饰器的框架:

def log(func):
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper @log
def now():
print('2018-6-14')

  Python装饰器,本质上就是一个高阶函数。作用是给其它函数增加新的功能。借用python的@语法,可以将一个高阶函数定义为装饰器。

@符号的作用

  但是,在学习廖雪峰老师的Python教程时,似懂非懂,尤其是看到@这个符号的时候,感觉一头雾水。现在回想来看,只要百度一下就能知道@符号在Python中的作用。它的作用就是修饰一个函数。位置在被修饰的函数的前一行,@之后是修饰函数的函数。 例如上述的 @log 起到的作用就是相当于执行了语句: now = log(now) ,现在或许难以理解这行代码的作用。接下来,进行一个对比,就能知道装饰器的威力了。

使用装饰器之前

#给下列函数增加新功能:调用函数时,打印函数名。
#要求:()不改变函数的定义,不改变函数的调用方式。
def now():
print('2015-3-25')

#增加一个高级函数
def call_name(func):
def wrapper(*args, **kw):
print('call %s()' % func.__name__)
return func(*args, **kw)
return wrapper

#调用now函数
now = call_name(now) #调用方式还是改变了(增加了一行)
now()

使用装饰器之后

#给下列函数增加新功能:调用函数时,打印函数名。
#要求:()不改变函数的定义,不改变函数的调用方式。 #写一个装饰器
def call_name(func):
def wrapper(*args, **kw):
print('call %s()' % func.__name__)
return func(*args, **kw)
return wrapper @call_name #相当于执行语句 call_name(now)
def now():
print('2015-3-25') #调用now函数
now() #这才是真正没改变调用方式

  通过对比,我对装饰器的作用了解更加深刻了。下面是带参数的装饰器:

带参数的装饰器

  上例,如果装饰器call_name(func)本身还要带参数,那么需要更加复杂的高阶函数。

 def call_name(text):                   #text为装饰器的参数
def decorator(func):
def wrapper(*args, **kw):
print('%s call %s()' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator @call_name('execute ') #相当于 now = log('execute')(now)
def now():
print('2015-3-25') # 调用now函数
now()

装饰器练习

  设计一个decorator(装饰器),它可作用于任何函数上,并打印该函数的执行时间:

 import time

 import functools

 def metric(fn):
@functools.wraps(fn)
def wrapper(*args, **kw):
print('%s executed in %s' %
(fn.__name__, time.asctime(time.localtime(time.time()))))
return fn(*args, **kw)
return wrapper # 测试 @metric
def fast(x, y):
time.sleep(0.0012)
return x + y @metric
def slow(x, y, z):
time.sleep(0.1234)
return x * y * z f = fast(11, 22)
s = slow(11, 22, 33) print(f)
print(s) if f != 33:
print('测试失败!')
elif s != 7986:
print('测试失败!')
else:
print('测试成功!')

  编写一个decorator,能在函数调用的前后打印出'begin call'和'end call'的日志:

 def call_name(func):
def wrapper(*args, **kw):
print('begin call:')
print('call %s()' % func.__name__)
call = func(*args, **kw) #函数在此时调用
print('end call.')
return call
return wrapper @call_name
def now():
print('2015-3-25') # 调用now函数
now()

  加大难度,写出一个@call_name的decorator,使它既支持:

@log
def f():
pass

  又支持:

@log('execute')
def f():
pass

  源码实现:

 import functools

 def call_name(text):
if isinstance(text, str):      #通过参数能够判断两种模式
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print('%s call %s()' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator
else:
@functools.wraps(text)
def wrapper(*args, **kw):
print('call %s()' % text.__name__)
return text(*args, **kw)
return wrapper @call_name
def now():
print('2015-3-25') # 调用now函数
now()
												

【Python学习之二】装饰器的更多相关文章

  1. python学习笔记:装饰器2

    python的装饰器本质是函数,为了不改变装饰目标函数内部代码而增加额外功能而存在 一.一般装饰函数实例: import datetime def func_name(func):#定义一个装饰函数, ...

  2. Python学习——迭代器&生成器&装饰器

    一.迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素.迭代器仅 ...

  3. Python学习笔记012——装饰器

    1 装饰器 1.1装饰器定义 在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator). 1.2 装饰器分类 装饰器:函数装饰器,类装饰器,函数的装饰器,类的装饰器 装饰器:函数装饰函 ...

  4. python学习笔记(五):装饰器、生成器、内置函数、json

    一.装饰器 装饰器,这个器就是函数的意思,连起来,就是装饰函数,装饰器本身也是一个函数,它的作用是用来给其他函数添加新功能,比如说,我以前写了很多代码,系统已经上线了,但是性能比较不好,现在想把程序里 ...

  5. Python学习笔记:装饰器

    Python 装饰器的基本概念和应用 代码编写要遵循开放封闭原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即: 封闭:已 ...

  6. python学习之day5,装饰器,生成器,迭代器,json,pickle

    1.装饰器 import os import time def auth(type): def timeer(func): def inner(*args,**kwargs): start = tim ...

  7. python学习笔记之装饰器、递归、算法(第四天)

    参考老师的博客: 金角:http://www.cnblogs.com/alex3714/articles/5161349.html 银角:http://www.cnblogs.com/wupeiqi/ ...

  8. 从零开始的Python学习Episode 11——装饰器

    装饰器 装饰器是用来处理其他函数的函数,主要作用是在不修改原有函数的情况下添加新的功能,装饰器的返回值也是一个函数对象. 简单的装饰器 import time def show_time(f): de ...

  9. Python学习系列之装饰器

    装饰器的作用 装饰器用于装饰某个函数.方法或者类,它可以让这个函数执行之前或者执行之后做一些操作 手工实现一个装饰器 def outer(some_func): #装饰器 $1 def inner() ...

  10. Python学习日记(九) 装饰器函数

    1.import time a.time.time() 获取到当前的时间,返回值为浮点型 import time print(time.time()) #1565422783.6497557 b.ti ...

随机推荐

  1. 【书评】【不推荐】《TensorFlow:实战Google深度学习框架》(第2版)

    参考书 <TensorFlow:实战Google深度学习框架>(第2版) 这本书我老老实实从头到尾看了一遍(实际上是看到第9章,刚看完,后面的实在看不下去了,但还是会坚持看的),所有的代码 ...

  2. python自建模块显示说明与详情

    通常我们自建模块放在/usr/lib/python2.7/site-packages下面,这样可以python就可以进行调用. 但是,自建模块也要有详细的说明情况,例如查help,可以看出来模块的作用 ...

  3. day01 继承

  4. VMWare版本兼容问题处理

    其他电脑拷贝过来的VMWare虚拟机启动时报错: 在虚拟机根目录中找到"vmx"后缀文件,发现原来的VM版本为14,而本地的VMWare版本为11. virtualHW.versi ...

  5. Incorrect configuration: namenode address dfs.namenode.servicerpc-address or dfs.namenode.rpc-address is not configured.

    在搭建Hadoop集群的时候,遇到了这样的一个报错. 就在启动HDFS调用命令: start-dfs.sh 的时候,报错: 然后输密码就一直很奇怪,反正一直运行不成功. 百度了半天,确定是core-s ...

  6. Linux--NiaoGe-Service-06

    Linux网络排错 思路: 硬件问题: 首先排除硬件故障,包括网线.Hub.Switch.Router.网卡.设备配置规则等等. 软件问题: 1.网卡的IP/Netmask设置错误 IP.Netmas ...

  7. HTML <form> 标签的 enctype

    form的enctype有三种 application/x-www-form-urlencoded 在发送前编码所有字符(默认) multipart/form-data 不对字符编码. 在使用包含文件 ...

  8. VMware下OSSIM 5.2.0的下载、安装和初步使用(图文详解)

    不多说,直接上干货! 入门阶段不建议选用最新的版本. 采用OSSIM 4.11 到 OSSIM5.0.3 之间任何版本做实验,sensor的状态都会是“V”.   建议,入门,采用OSSIM5.0.0 ...

  9. 从javaweb项目学习

    1.sql语句 在insert语句中需要插入查询出来的值. Insert into a (a1,a2,a3) values (1,select num from b where id=1,3) 这样写 ...

  10. Mysql如何为表字段添加索引???

    1.添加PRIMARY KEY(主键索引): ALTER TABLE `table_name` ADD PRIMARY KEY ( `column` ) 2.添加UNIQUE(唯一索引) : ALTE ...