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+django实现文件下载
Jan 17 Python
Python3使用requests登录人人影视网站的方法
May 11 Python
python使用xlrd与xlwt对excel的读写和格式设定
Jan 21 Python
python如何让类支持比较运算
Mar 20 Python
python矩阵转换为一维数组的实例
Jun 05 Python
python 将print输出的内容保存到txt文件中
Jul 17 Python
Python二叉搜索树与双向链表转换算法示例
Mar 02 Python
python使用Plotly绘图工具绘制散点图、线形图
Apr 02 Python
python使用opencv在Windows下调用摄像头实现解析
Nov 26 Python
Python 音频生成器的实现示例
Dec 24 Python
Python键鼠操作自动化库PyAutoGUI简介(小结)
May 17 Python
python实现图书馆抢座(自动预约)功能的示例代码
Sep 29 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
这东西价格,可以买几台TECSUN S-2000
2021/03/02 无线电
一个显示天气预报的程序
2006/10/09 PHP
PHP获取url的函数代码
2011/08/02 PHP
PHP页面实现定时跳转的方法
2014/10/31 PHP
php的sso单点登录实现方法
2015/01/08 PHP
php安装ssh2扩展的方法【Linux平台】
2016/07/20 PHP
TNC vs IO BO3 第二场2.13
2021/03/10 DOTA
javascript 面向对象,实现namespace,class,继承,重载
2009/10/29 Javascript
javascript 异步页面查询实现代码(asp.net)
2010/05/26 Javascript
基于jQuery的Spin Button自定义文本框数值自增或自减
2010/07/17 Javascript
php对mongodb的扩展(初识如故)
2012/11/11 Javascript
在JavaScript应用中使用RequireJS来实现延迟加载
2015/07/01 Javascript
js HTML5 Ajax实现文件上传进度条功能
2016/02/13 Javascript
JS中的eval 为什么加括号
2016/04/13 Javascript
老生常谈遮罩层 滚动条的问题
2016/04/29 Javascript
使用jquery判断一个元素是否含有一个指定的类(class)实例
2017/02/12 Javascript
JS设置随机出现2个数字的实例代码
2017/07/19 Javascript
JavaScript实现兼容IE6的收起折叠与展开效果实例
2017/09/20 Javascript
微信小程序wx:for和wx:for-item的用法详解
2018/04/01 Javascript
微信小程序如何获取手机验证码
2018/11/04 Javascript
Nodejs处理异常操作示例
2018/12/25 NodeJs
小程序实现搜索界面 小程序实现推荐搜索列表效果
2019/05/18 Javascript
vue如何自动化打包测试环境和正式环境的dist/test文件
2019/06/06 Javascript
在react-antd中弹出层form内容传递给父组件的操作
2020/10/24 Javascript
在Python中使用cookielib和urllib2配合PyQuery抓取网页信息
2015/04/25 Python
Python实现比较两个列表(list)范围
2015/06/12 Python
Python 利用内置set函数对字符串和列表进行去重的方法
2018/06/29 Python
PowerBI和Python关于数据分析的对比
2019/07/11 Python
python图形绘制奥运五环实例讲解
2019/09/14 Python
Weblogc domain问题
2014/01/27 面试题
机械电子工程毕业生自荐信
2013/11/23 职场文书
校园新闻广播稿
2014/01/10 职场文书
社区灵活就业证明
2014/11/03 职场文书
2016年春节慰问信息大全
2015/11/30 职场文书
考教师资格证不要错过的4个最佳时机
2019/07/17 职场文书
Python爬虫框架之Scrapy中Spider的用法
2021/06/28 Python