python中的装饰器详解


Posted in Python onApril 13, 2015

在了解装饰器的之前一定要先了解函数作为参数传递, 什么是函数内嵌,请参考我之前写的博客函数简介

因为在python里面,函数也是对象,也可以作为参数进行传递.python装饰器本质也是一种特殊函数,它接收的参数是函数对象,然后动态地函数参数添加额外的功能,而不用修改原有的函数对象.python装饰器传入的参数是函数,返回的值也是函数!
python装饰器思想有点类似设计模式的装饰模式, 其意图是动态地给函数对象添加额外的功能.比如像增加日志打印的功能,有点面向切面编程(AOP)的感觉.
装饰器语法

以@开头,接着后面跟着的是装饰器的名字和可选的参数.装饰器语法是一种语法糖.
格式如下

@decomaker(deco_args)

    def foo(func_opt_args)

可以组合,等价于foo = g(f(foo))
@g

@f

def foo():

    statement

简单装饰器

实例

#!/usr/bin/python

def  deco(func):

    print 'start'

    func()

    print 'end'

    return func
@deco

def foo():

    print 'In foo'
foo()

foo()

输出
start

In foo

end

In foo

In foo

带内嵌函数装饰器

内嵌函数保证每次新函数都被调用.而且被装饰的函数可以带有参数.
实例

def  deco(func):

    def _deco(x):    #该函数为内嵌函数

        print 'start'

        func(x)

        print 'end' 

    return _deco
@deco

def foo(x):

    print 'In foo, get value is: %d' % x
foo(123456)

输出:
start

In foo, get value is: 123456

end

带参数的装饰器

需要自己返回以函数作为参数的装饰器。换句话说,decomaker()用 deco_args 做了些事并返回函数对象,而该函数对象正是以 foo 作为其参数的装饰器。简单的说来:foo=decomaker(deco_args)(foo)

实例

def deco(arg):

    def wrapper1(func):

        def _deco(x):

            print "get type is: ", arg

            func(x)

        return _deco
    def wrapper2(func):

        def _deco(x):

            func(x)

            print "get type is: ", arg

        return _deco
    if arg == 'type1':

        return wrapper1

    else:

        return wrapper2
@deco("type2")

def foo(x):

    print 'In foo: ', x
foo(123)

输出
In foo:  123

get type is:  type2

总结

装饰器本质是高阶的函数,可以装饰其他函数,增加被装饰函数的功能,但不能覆盖或改变被装饰函数原有的行为.对于被装饰的函数来说,装饰器是透明的.装饰器传入参数为函数,返回的函数是被装饰的函数.最后我们来实现给一个函数添加打印日志的功能,而不用改变这个函数.

#!/usr/bin/python

#coding=utf-8

import functools
def log(prefix, suffix):

    def deco(func):

        @functools.wraps(func)

        def wrapper(*args, **kargs):

            print '%s log start' % prefix

            print('get a is: %s' % args[0])

            print('get b is: %s' % args[1])

            print('get c is: %s' % args[2])

            print('get d is: %s' % kargs['d'])

            print('get d is: %s' % kargs['f'])

            func(*args, **kargs)

            print '%s log end' % suffix

        return wrapper

    return deco
@log('logstart', 'logend')

def test(a, b, c, d, f):

    print 'call func name is: %s' % test.__name__
test(1, 2, 3, d = 'dddd', f = 'ffff')

输出:
logstart log start

get a is: 1

get b is: 2

get c is: 3

get d is: dddd

get d is: ffff

call func name is: test

logend log end
Python 相关文章推荐
举例讲解Python的Tornado框架实现数据可视化的教程
May 02 Python
Python使用爬虫猜密码
Feb 19 Python
利用Python批量生成任意尺寸的图片
Aug 29 Python
浅谈对yield的初步理解
May 29 Python
Python实现XML文件解析的示例代码
Feb 05 Python
python使用json序列化datetime类型实例解析
Feb 11 Python
Python实现个人微信号自动监控告警的示例
Jul 03 Python
python实现的分析并统计nginx日志数据功能示例
Dec 21 Python
基于python爬取有道翻译过程图解
Mar 31 Python
selenium切换标签页解决get超时问题的完整代码
Aug 30 Python
解决Pycharm 运行后没有输出的问题
Feb 05 Python
Python之matplotlib绘制饼图
Apr 13 Python
Python生成器(Generator)详解
Apr 13 #Python
Python中函数的多种格式和使用实例及小技巧
Apr 13 #Python
在Python中使用SimpleParse模块进行解析的教程
Apr 11 #Python
Python的动态重新封装的教程
Apr 11 #Python
简单的Python的curses库使用教程
Apr 11 #Python
详解Python中的文本处理
Apr 11 #Python
状态机的概念和在Python下使用状态机的教程
Apr 11 #Python
You might like
PHP curl使用实例
2015/07/02 PHP
PHP实现全角字符转为半角方法汇总
2015/07/09 PHP
PHP数组操作类实例
2015/07/11 PHP
PHP实现C#山寨ArrayList的方法
2015/07/16 PHP
php+ajax实现无刷新文件上传功能(ajaxuploadfile)
2018/02/11 PHP
去除链接虚线全面分析总结
2006/08/15 Javascript
基于jquery的无刷新分页技术
2011/06/11 Javascript
在jQuery ajax中按钮button和submit的区别分析
2012/10/07 Javascript
原生JS实现表单checkbook获取已选择的值
2013/07/21 Javascript
ubuntu下安装nodejs以及升级的办法
2015/05/08 NodeJs
详解AngularJS过滤器的使用
2016/03/11 Javascript
jQuery弹出遮罩层效果完整示例
2016/09/13 Javascript
jQuery EasyUI中的日期控件DateBox修改方法
2016/11/09 Javascript
JavaScript数组操作详解
2017/02/04 Javascript
jQury Ajax使用Token验证身份实例代码
2017/09/22 Javascript
JS实现提交表单前的数字及邮箱校检功能
2017/11/13 Javascript
浅析vue-router jquery和params传参(接收参数)$router $route的区别
2018/08/03 jQuery
通过JS运行机制的角度说说作用域
2019/03/12 Javascript
简单通过settimeout看javascript的运行机制
2019/05/10 Javascript
详解Vue之计算属性
2020/06/20 Javascript
简单了解Vue computed属性及watch区别
2020/07/10 Javascript
教你安装python Django(图文)
2013/11/04 Python
基于python脚本实现软件的注册功能(机器码+注册码机制)
2016/10/09 Python
python+selenium识别验证码并登录的示例代码
2017/12/21 Python
微信跳一跳python代码实现
2018/01/05 Python
一行python实现树形结构的方法
2019/08/09 Python
Python logging设置和logger解析
2019/08/28 Python
python 模拟贷款卡号生成规则过程解析
2019/08/30 Python
Python实现不规则图形填充的思路
2020/02/02 Python
旅游管理专业学生求职信
2013/09/28 职场文书
药学专业个人的自我评价
2013/12/31 职场文书
向国旗敬礼活动小结
2014/09/27 职场文书
2015年社区综治工作总结
2015/04/21 职场文书
关于Vue Router的10条高级技巧总结
2021/05/06 Vue.js
《勇者辞职不干了》上卷BD发售宣传CM公开
2022/04/08 日漫
Python函数对象与闭包函数
2022/04/13 Python