装饰器

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

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. ADO winform注册

    前面我们了解了如何实现登录,现在.我们来讨论如何实现注册功能,注册其实就是 通过程序,往数据库中新增数据.首先我们同样连接到数据库,同上页一样创建连接,然后 打开连接.之后我们就要去获取我们输入到文本 ...

  2. random 库

    random 是使用随机数的python 标准库 ——为随机数:采用梅森旋转算法生成的(伪)随机序列中的元素 —— import random 基本随机数函数:seed(),random() 扩展随机 ...

  3. Excel - 使用公式将秒转换为分+秒

    场景 现在有个需求:将Excel里的时间转换为分+秒的格式,如下: time(second) time(min+second) 482.712 XXmin,XXs 480.737 XXmin,XXs ...

  4. android videoView 加载等待

    final Handler handler = new Handler(); Runnable runnable = new Runnable() { public void run() { int ...

  5. [题解](堆)luogu_P1631序列合并

    思路来自题解 作者: Red_w1nE 更新时间: 2016-11-13 20:46 在Ta的博客查看  72 最近有点忙 没时间贴代码了== [分析] 首先,把A和B两个序列分别从小到大排序,变成两 ...

  6. ZOJ3329(数学推导+期望递推)

    要点: 1.期望的套路,要求n以上的期望,则设dp[i]为i分距离终点的期望步数,则终点dp值为0,答案是dp[0]. 2.此题主要在于数学推导,一方面是要写出dp[i] = 什么,虽然一大串但是思维 ...

  7. Codeforces 526F Pudding Monsters

    先把题目抽象一下: 有一个静态的数组,求有多少个区间[i,j]满足:j-i==max{ai,...,aj}-min{ai,...,aj} 也就是要求max-min+i-j==0的区间数 所以肿么做呢? ...

  8. js对象引用赋值后

    a={f:1} b={} b.a=a console.log(b.a) a.b=2 console.log(b.a) a={f:1} b={} b.a=a console.log(b.a) a={b: ...

  9. hihocoder1032 最长回文子串

    思路: manacher模板. 实现: #include <iostream> #include <cstring> using namespace std; ]; strin ...

  10. iOS --runtime理解

    iOS~runtime理解 Runtime是想要做好iOS开发,或者说是真正的深刻的掌握OC这门语言所必需理解的东西.最近在学习Runtime,有自己的一些心得,整理如下,一为 查阅方便二为 或许能给 ...