我们先看一个闭包的例子:

from time import ctime

def before_call(f):
def wrapped(*args, **kargs):
print 'before calling, now is %s' % ctime()
return f(*args, **kargs)
return wrapped def test(name):
print 'hello, %s' % (name) if __name__ == '__main__':
before_call(test)("lucky")

我们先看运行结果:

~/Documents/py python 2.py
before calling, now is Sat Dec 27 21:30:18 2014
hello, lucky

上面的代码使用了闭包,因为子函数wrapped将父函数的内部变量f与之绑定。

这样,wrapped这个闭包函数,实际上先打印时间,然后调用f,所以正如结果打印的一般,before_call起到的是一种装饰的作用。

 

这里我扩展它的功能,增加一个调用函数后,打印时间:

from time import ctime

def before_call(f):
def wrapped(*args, **kargs):
print 'before calling, now is %s' % ctime()
return f(*args, **kargs)
return wrapped def after_call(f):
def wrapped(*args, **kargs):
try:
return f(*args, **kargs)
finally:
print 'after calling, now is %s' % ctime()
return wrapped def test(name):
print 'hello, %s' % (name) if __name__ == '__main__':
before_call(test)("lucky")
after_call(test)("peter")
before_call(after_call(test))("john")
after_call(before_call(test))('marry')

运行结果为:

~/Documents/py python 2.py
before calling, now is Sat Dec 27 21:37:24 2014
hello, lucky
hello, peter
after calling, now is Sat Dec 27 21:37:24 2014
before calling, now is Sat Dec 27 21:37:24 2014
hello, john
after calling, now is Sat Dec 27 21:37:24 2014
before calling, now is Sat Dec 27 21:37:24 2014
hello, marry
after calling, now is Sat Dec 27 21:37:24 2014

运行结果是正确的。注意最后两个,顺序交换了,对结果无影响。

 

下面我们再包装一层:

def after_call():
def after(f):
def wrapped(*args, **kargs):
try:
return f(*args, **kargs)
finally:
print 'after calling, now is %s' % ctime()
return wrapped
return after def before_call():
def before(f):
def wrapped(*args, **kargs):
print 'before calling, now is %s' % ctime()
return f(*args, **kargs)
return wrapped
return before

那么如何使用呢?这里就是python装饰器的语法,

如果我们这样使用:

@before_call()
def test(name):
print 'hello, %s' % (name) if __name__ == '__main__':
test("lucky")

注意test函数前加了装饰的符号。

还可以这样:

@after_call()
def test(name):
print 'hello, %s' % (name)

甚至可以嵌套多层:

@before_call()
@after_call()
def test(name):
print 'hello, %s' % (name)

 

这就是python中装饰器的原理,内部采用了闭包。

Python闭包的高级应用-装饰器的实现的更多相关文章

  1. python高级之装饰器

    python高级之装饰器 本节内容 高阶函数 嵌套函数及闭包 装饰器 装饰器带参数 装饰器的嵌套 functools.wraps模块 递归函数被装饰 1.高阶函数 高阶函数的定义: 满足下面两个条件之 ...

  2. 第二篇:python高级之装饰器

    python高级之装饰器   python高级之装饰器 本节内容 高阶函数 嵌套函数及闭包 装饰器 装饰器带参数 装饰器的嵌套 functools.wraps模块 递归函数被装饰 1.高阶函数 高阶函 ...

  3. python中函数总结之装饰器闭包

    1.前言 函数也是一个对象,从而可以增加属性,使用句点来表示属性. 如果内部函数的定义包含了在外部函数中定义的对象的引用(外部对象可以是在外部函数之外),那么内部函数被称之为闭包. 2.装饰器 装饰器 ...

  4. 简学Python第四章__装饰器、迭代器、列表生成式

    Python第四章__装饰器.迭代器 欢迎加入Linux_Python学习群  群号:478616847 目录: 列表生成式 生成器 迭代器 单层装饰器(无参) 多层装饰器(有参) 冒泡算法 代码开发 ...

  5. Python全栈开发之---装饰器

    1.装饰器的形成过程 import time def func1(): print('in func1') def timer(func): def inner(): start = time.tim ...

  6. 初学 Python(十五)——装饰器

    初学 Python(十五)--装饰器 初学 Python,主要整理一些学习到的知识点,这次是生成器. #-*- coding:utf-8 -*- import functools def curren ...

  7. 十一. Python基础(11)—补充: 作用域 & 装饰器

    十一. Python基础(11)-补充: 作用域 & 装饰器 1 ● Python的作用域补遗 在C/C++等语言中, if语句等控制结构(control structure)会产生新的作用域 ...

  8. Python 函数修饰符(装饰器)的使用

     Python 函数修饰符(装饰器)的使用 1.  修饰符的来源修饰符是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等. 修饰符是解决这类问题的绝佳设计, ...

  9. Python 标准库中的装饰器

    题目描述 1.简单举例 Python 标准库中的装饰器 2.说说你用过的 Python 标准库中的装饰器 1. 首先,我们比较熟悉,也是比较常用的 Python 标准库提供的装饰器有:property ...

随机推荐

  1. selenium 警告框处理 (弹窗处理)

    在web应用中常常会遇见很多用JavaScript编写的alert .confirm 以及prompt 弹窗,这是就需要driver.switchTo().alert()来选取(定位)警告弹窗.再对弹 ...

  2. Go语言,互斥锁使用

    package main import ( "fmt" "runtime" "sync" ) var ( counter int wg sy ...

  3. <Linux性能调优指南>主要思路流程

    网上IBM很早放出的一本免费电子书, 十来年了,参考意义还是很大. 国内有翻译成中文在线阅读的版本. 见如下两个URL Linux Performance and Tuning Guidelines ...

  4. oracle 11g在大表中添加字段及默认值--加速

    今天遇到这个问题了.简单的增加语句,默认SQLPLUS执行,却会超时. 要增加客户端的TIMEOUT时间才可以解决.(感觉超过两三分钟,默认超时30秒) 另外, 也可以用两步操作(1,增加字段,2,修 ...

  5. shell字符串变量的特异功能:字符串的替换(${str/源模式/目标模式},${str//源模式/目标模式})、截断

    https://blog.csdn.net/wzb56_earl/article/details/6953612

  6. 记录一下安卓本地文件File处理的问题

    在项目中更新软件下载更新包的时候删除系统文件夹会报错导致下载失败 研究了下是因为目录不存在导致的由于系统自带下载目录,但是一些极限操作当目录不存在时就需要处理下 项目中的解决方案 File f = n ...

  7. 浅谈replace()

    replace()简单介绍 replace()基本语法是String.replace(searchValue,replaceValue),其中searchValue为字符串或者正则,replaceVa ...

  8. bufferknife框架的正确使用方式 -终于他么知道了

    1.由于ButterKnife从7.x到8.x后,运行时和编译器被分开来,你还需要配置 apt ‘com.jakewharton:butterknife-compiler:8.1.0’,在projec ...

  9. oracle null 相关的另外2个方法

  10. Fiddler 高级用法:Fiddler Script 与 HTTP 断点调试

    转载自 https://my.oschina.net/leejun2005/blog/399108 1.Fiddler Script 1.1 Fiddler Script简介 在web前端开发的过程中 ...