理解Python的装饰器
看Flask文档时候看到关于cache的装饰器,有这么一段代码:
def cached(timeout=5 * 60, key=’view/%s’):
def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
cache_key = key % request.path
rv = cache.get(cache_key)
if rv is not None:
return rv
rv = f(*args, **kwargs)
cache.set(cache_key, rv, timeout=timeout)
return rv
return decorated_function
return decorator
之前也略懂装饰器,但是仔细一看发现了区别。
一般的装饰器代码是这样的:
def login_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if g.user is None:
return redirect(url_for(’login’, next=request.url))
return f(*args, **kwargs)
return decorated_function
看出区别了吗?
第一个里面有两层def,第二个只有一层!
我的好奇心一下就上来了,非要把这个东西搞明白不可。
研究了一会总算研究明白了,下面就开始讲解吧。
首先理解一般的装饰器到底是怎么工作的:
def login_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if g.user is None:
return redirect(url_for(’login’, next=request.url))
return f(*args, **kwargs)
return decorated_function @login_required
def test():
print "haha"
我们用login_required装饰了test函数,那么实际上执行的语句可以理解成这样:
test = login_required(test)
也就是说,现在test变成了login_required(test)的执行结果,也就是变成了decorated_function函数。
所以我们每次执行test的时候,其实执行的就是decorated_function,而原来的test函数就变成了decorated_function中的f函数。实现了装饰功能。
下面我们看看两层嵌套的装饰器到底是怎么工作的:
def cached(timeout=5 * 60, key=’view/%s’):
def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
cache_key = key % request.path
rv = cache.get(cache_key)
if rv is not None:
return rv
rv = f(*args, **kwargs)
cache.set(cache_key, rv, timeout=timeout)
return rv
return decorated_function
return decorator @cached(100)
def test():
pass
好像没什么区别?
再仔细看看!
@cached(100)
这里多了个参数!
是的,秘密就在这个参数。
加了参数之后,装饰器的装饰过程变成了两步:
cached_temp = cached(100)
test = cached_temp(test)
Python内部肯定没有cached_temp这个变量,这是我加的。不过实际的执行过程就是这么个顺序,这下就一目了然了吧!
首先运行cached(100),这时候返回的是第一层def,也就是真正的装饰器。
然后运行cached_temp(test),这时候返回了第二层def,这步就和一般的装饰器一样了。
我们总结一下,嵌套两层def的目的就是实现“带参装饰器”,相当于可以通过参数来定制一个装饰器,然后再应用到函数上。
明白了吗?
理解Python的装饰器的更多相关文章
- 正确理解python的装饰器
一直在用别人写的装饰器,从来没有对其原理进行深入的探究.今天趁有点闲着的时间,把装饰器的原理好好看了一遍,做一下整理. 一.装饰器的基本原理 装饰器就是一个可以接受调用也可以返回调用的调用.装饰器本身 ...
- 理解Python中的装饰器//这篇文章将python的装饰器来龙去脉说的很清楚,故转过来存档
转自:http://www.cnblogs.com/rollenholt/archive/2012/05/02/2479833.html 这篇文章将python的装饰器来龙去脉说的很清楚,故转过来存档 ...
- 关于python的装饰器(初解)
在python中,装饰器(decorator)是一个主要的函数,在工作中,有了装饰器简直如虎添翼,许多公司面试题也会考装饰器,而装饰器的意思又很难让人理解. python中,装饰器是一个帮函数动态增加 ...
- 【转】详解Python的装饰器
原文链接:http://python.jobbole.com/86717/ Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现 ...
- python之装饰器详解
这几天翻看python语法,看到装饰器这里着实卡了一阵,最初认为也就是个函数指针的用法,但仔细研究后发现,不止这么简单. 首先很多资料将装饰器定义为AOP的范畴,也就是Aspect Oriented ...
- python基础—装饰器
python基础-装饰器 定义:一个函数,可以接受一个函数作为参数,对该函数进行一些包装,不改变函数的本身. def foo(): return 123 a=foo(); b=foo; print(a ...
- 详解Python的装饰器
Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现了say_hello()和say_goodbye()两个函数. def sa ...
- 【转】Python之装饰器
[转]Python之装饰器 本节内容 必要知识回顾 情景模拟 装饰器的概念及实现原理 回马枪(带参数的装饰器) 一. 必要知识回顾 在开始说装饰器之前,需要大家熟悉之前说过的相关知识点: 函数即“变量 ...
- 如何用python的装饰器定义一个像C++一样的强类型函数
Python作为一个动态的脚本语言,其函数在定义时是不需要指出参数的类型,也不需要指出函数是否有返回值.本文将介绍如何使用python的装饰器来定义一个像C++那样的强类型函数.接下去,先介绍 ...
随机推荐
- ASP.NET CORE 边学边记之 SwaggerUI简单配置
前言 当使用 ASP.NET CORE 开发WebApi程序时候,一般使用SwaggerUI生成接口文档.本文记录最简单的一个配置.(生成的文档无注释) 操作 首先安装Nuget包. 然后在Start ...
- VC++读写*.ini配置文件
ini文件(即Initialization file),这种类型的文件中通常存放的是一个程序的初始化信息.ini文件由若干个节(Section)组成,每个Section由若干键(Key)组成,每个Ke ...
- JavaSE注释
注解在JavaSE中算是比较高级的一种用法了,为什么要学习注解,我想大概有以下几个原因: 1. 可以更深层次地学习Java,理解Java的思想. 2. 有了注解的基础,能够方便阅读各种框架的源码,比如 ...
- Race UVA - 12034(dp+打表)
Disky and Sooma, two of the biggest mega minds of Bangladesh went to a far country. They ate, coded ...
- DHCP, NAT
DHCP Dynamic Host Configuration Protocol(动态主机配置协议) (RFC 2131) Bootstrap Protocol BOOTP(引导程序协议) allow ...
- 【2017002】C#FTP上传文件
//上传文件 public static Boolean FtpUpload(string ftpPath, string localFile, FtpServer svr) { //检查目录是否存在 ...
- 轻量ORM-SqlRepoEx (十)SqlRepoEx Nuget包下载说明
ORM-SqlRepoEx 是 .Net平台下兼容.NET Standard 2.0,一个实现以Lambda表达式转转换标准SQL语句,使用强类型操作数据的轻量级ORM工具,在减少魔法字串同时,通过灵 ...
- JavaScript变量声明及赋值
1.变量声明 var a; //声明一个变量 a var b,c,d; //同时申明多个变量时,变量名之间用逗号隔开 console.log(a); //在控制台显示变量a的值,输出为undefine ...
- H5输入框在输入信息的时候 页面会变形 并且在页面不变形的时候 键盘会遮挡 输入框的解决办法
$(document).ready(function () { $('body').css({'height':$(window).height()})});//这行是解决输入框在输入信息弹出键盘后页 ...
- 误操作yum导致error: rpmdb解决方法
错误:[root@test ~]# yum makecache error: rpmdb: BDB0113 Thread/process 18967/139716328294400 failed: B ...