装饰器

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

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. maven - 安装目录详解

    从 Apache Maven 官网下载 Maven 的安装包并解压之后,进入安装目录,我们会看到如下内容: 接下来我们分别解读目录的内容及其功能 bin 包含了mvn运行的脚本,在命令行输入任意一条m ...

  2. one jar(转)

    http://blog.csdn.net/kabini/article/details/1598827

  3. Java泛型学习摘抄

  4. properties 文件注意事项

    不要使用""双引号包裹内容 db.validationQuery="select 1"比如上面这种是错误的,下面的是正确的写法 db.validationQue ...

  5. IP服务-1-ARP和代理ARP

    代理ARP常被人忽视,因为现在基本不用了

  6. Codeforces Round #542(Div. 2) B.Two Cakes

    链接:https://codeforces.com/contest/1130/problem/B 题意: 给定n和 2 * n个数,表示i位置卖ai层蛋糕, 有两个人在1号,必须严格按照1-n的顺序买 ...

  7. pip 的简单安装与基本使用

    pip 是 Python 著名的包管理工具,在 Python 开发中必不可少.本文只介绍各平台最新可用并且最简单的 pip 安装方式,以方便初学者和不会敲代码只需通过 pip 安装特定工具的小伙伴们. ...

  8. MySQL简单的确定瓶颈

    如果接到报警可能需要ssh看看瓶颈是什么,怎么下手 确定os层 确定磁盘是否够用的:df –h 再看看系统整体状态: top 哪些进程占用资源比较多,能杀就杀 系统的负载 vmstat看看wa值,r列 ...

  9. 头部和信号栏一个颜色appcloud

    <header id="header" > <ul > <li class="active" onclick="api. ...

  10. How many '1's are there题解

    Description: Description: 第一行输入数字n(n<=50),表示有n组测试用例,第2到第n+1行每行输入数m(m为整数),统计并输出m用二进制表示时,1的个数. 例如:m ...