【Python学习之二】装饰器
装饰器
首先,给出装饰器的框架:
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学习之二】装饰器的更多相关文章
- python学习笔记:装饰器2
python的装饰器本质是函数,为了不改变装饰目标函数内部代码而增加额外功能而存在 一.一般装饰函数实例: import datetime def func_name(func):#定义一个装饰函数, ...
- Python学习——迭代器&生成器&装饰器
一.迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素.迭代器仅 ...
- Python学习笔记012——装饰器
1 装饰器 1.1装饰器定义 在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator). 1.2 装饰器分类 装饰器:函数装饰器,类装饰器,函数的装饰器,类的装饰器 装饰器:函数装饰函 ...
- python学习笔记(五):装饰器、生成器、内置函数、json
一.装饰器 装饰器,这个器就是函数的意思,连起来,就是装饰函数,装饰器本身也是一个函数,它的作用是用来给其他函数添加新功能,比如说,我以前写了很多代码,系统已经上线了,但是性能比较不好,现在想把程序里 ...
- Python学习笔记:装饰器
Python 装饰器的基本概念和应用 代码编写要遵循开放封闭原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即: 封闭:已 ...
- python学习之day5,装饰器,生成器,迭代器,json,pickle
1.装饰器 import os import time def auth(type): def timeer(func): def inner(*args,**kwargs): start = tim ...
- python学习笔记之装饰器、递归、算法(第四天)
参考老师的博客: 金角:http://www.cnblogs.com/alex3714/articles/5161349.html 银角:http://www.cnblogs.com/wupeiqi/ ...
- 从零开始的Python学习Episode 11——装饰器
装饰器 装饰器是用来处理其他函数的函数,主要作用是在不修改原有函数的情况下添加新的功能,装饰器的返回值也是一个函数对象. 简单的装饰器 import time def show_time(f): de ...
- Python学习系列之装饰器
装饰器的作用 装饰器用于装饰某个函数.方法或者类,它可以让这个函数执行之前或者执行之后做一些操作 手工实现一个装饰器 def outer(some_func): #装饰器 $1 def inner() ...
- Python学习日记(九) 装饰器函数
1.import time a.time.time() 获取到当前的时间,返回值为浮点型 import time print(time.time()) #1565422783.6497557 b.ti ...
随机推荐
- 小程序video置顶
page { overflow-y: none; height: 100vh; } .page__hd_media { position: fixed; width:100vw; top:; heig ...
- [題解](單調隊列/水)luogu_P3088擠奶牛
d長度內區間最大值,單調隊列維護即可 由於需要滿足左右同時有2倍高度的牛才能更新答案,所以正反跑兩次 #include<bits/stdc++.h> using namespace std ...
- Qt 进程和线程之一:运行一个进程和进程间通信
Qt提供了对进程和线程的支持.本节讲述了怎样在Qt应用程序中启动一个进程,以及几种常用的进程间通信方法.如果对进程和线程的概念不是很了解,可以看我的另一篇博客:[多进程和多线程的概念. 设计应用程序时 ...
- rtos概要
一 RTOS如何调试: 静态调试帮不上忙,因为嵌入式系统都是动态系统 ,要借助基于RTOS系统的可视化分析 :Micriµm 的 µC/Probe ,SEGGER 的 SystemView ,Perc ...
- PHP中的文件操作
文件系统的概述 任何类型的变量在运行的时候都是将其加载到内存里面.但是内存有一个特点:CPU读取内存的速度很快,但是一旦断电,内存里面的数据就会消失.如果要持久的保存数据,有两种方法:将数据存储到 ...
- java中 awt Graphics2D
Graphics2D ,Graphics 类,提供了对几何形状.坐标转换.颜色管理和文本布局更为复杂的控制.它是用于在 Java(tm) 平台上呈现二维形状.文本和图像的基础类.验证码生成可以用到此类 ...
- 通过Chrome执行watir-webdriver
1.http://code.google.com/p/chromedriver/downloads/list 下载chromedriver驱动文件chromedriver.exe 2.把驱动文件放在 ...
- Aop第一节
什么是AOP AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善.OOP引入 ...
- Android Theme.Dialog 到光 AppCompatDialog
我用在我的 style.xml 作为主要应用程序主题 <style name="AppTheme" parent="Theme.AppCompat.Light&qu ...
- 使用POI创建word表格-在表格单元格中创建子表格
要实现的功能如下:表格中的单元格中有子表格 实现代码如下: XWPFParagraph cellPara = row.getCell(j).getParagraphArray(0); //row.ge ...