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使用PIL模块实现给图片打水印的方法
May 22 Python
Python的Django框架中的Context使用
Jul 15 Python
Python Socket实现简单TCP Server/client功能示例
Aug 05 Python
基于python3 OpenCV3实现静态图片人脸识别
May 25 Python
django认证系统实现自定义权限管理的方法
Jul 16 Python
python实现文本界面网络聊天室
Dec 12 Python
手把手教你使用Python创建微信机器人
Apr 29 Python
Django 用户认证组件使用详解
Jul 23 Python
Django模板导入母版继承和自定义返回Html片段过程解析
Sep 18 Python
Python分析最近大火的网剧《隐秘的角落》
Jul 02 Python
浅谈python 类方法/静态方法
Sep 18 Python
filter使用python3代码进行迭代元素的实例详解
Dec 03 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 empty() 检查一个变量是否为空
2011/11/10 PHP
jQuery 通过事件委派一次绑定多种事件,以减少事件冗余
2010/06/30 Javascript
兼容ie、firefox的图片自动缩放的css跟js代码分享
2013/08/12 Javascript
JavaScript中的数组操作介绍
2014/12/30 Javascript
jQuery simplePage+AJAX plus分页插件用法实例
2016/02/17 Javascript
jQuery图片前后对比插件beforeAfter用法示例【附demo源码下载】
2016/09/20 Javascript
Bootstrap Table使用心得总结
2016/11/29 Javascript
JavaScript正则获取地址栏中参数的方法
2017/03/02 Javascript
JavaScrpt的面向对象全面解析
2017/05/09 Javascript
nodejs中用npm初始化来创建package.json的实例讲解
2018/10/10 NodeJs
vue实现在v-html的html字符串中绑定事件
2019/10/28 Javascript
antd 表格列宽自适应方法以及错误处理操作
2020/10/27 Javascript
如何利用nodejs实现命令行游戏
2020/11/24 NodeJs
Python实现的HTTP并发测试完整示例
2020/04/23 Python
python实现批量监控网站
2016/09/09 Python
Python实现JSON反序列化类对象的示例
2018/01/31 Python
python实现淘宝秒杀脚本
2020/06/23 Python
在python中对变量判断是否为None的三种方法总结
2019/01/23 Python
python爬取微信公众号文章的方法
2019/02/26 Python
python flask解析json数据不完整的解决方法
2019/05/26 Python
django实现将后台model对象转换成json对象并传递给前端jquery
2020/03/16 Python
Python flask框架端口失效解决方案
2020/06/04 Python
Python之字典添加元素的几种方法
2020/09/30 Python
python Yaml、Json、Dict之间的转化
2020/10/19 Python
Python爬虫抓取论坛关键字过程解析
2020/10/19 Python
纯CSS实现菜单、导航栏的3D翻转动画效果
2014/04/23 HTML / CSS
美国知名的女性服饰品牌:LOFT(洛芙特)
2016/08/05 全球购物
世界第一曲奇连锁店:Mrs. Fields Cookies
2017/02/04 全球购物
文秘专业应届生求职信范文
2013/11/14 职场文书
淘宝活动策划方案
2014/02/06 职场文书
学校安全责任书范本
2014/07/23 职场文书
公司委托书怎么写
2014/08/02 职场文书
闪闪的红星观后感
2015/06/08 职场文书
mysql升级到5.7时,wordpress导数据报错1067的问题
2021/05/27 MySQL
如何用RabbitMQ和Swoole实现一个异步任务系统
2021/05/29 PHP
CSS 实现角标效果的完整代码
2022/06/28 HTML / CSS