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框架使用入门指引
Apr 15 Python
python实现复制整个目录的方法
May 12 Python
Python 专题五 列表基础知识(二维list排序、获取下标和处理txt文本实例)
Mar 20 Python
Python实现简易Web爬虫详解
Jan 03 Python
python语言中with as的用法使用详解
Feb 23 Python
pandas 两列时间相减换算为秒的方法
Apr 20 Python
Python3.5迭代器与生成器用法实例分析
Apr 30 Python
对pyqt5中QTabWidget的相关操作详解
Jun 21 Python
在python中利用numpy求解多项式以及多项式拟合的方法
Jul 03 Python
基于python实现判断字符串是否数字算法
Jul 10 Python
PyQT5速成教程之Qt Designer介绍与入门
Nov 02 Python
Python 多线程之threading 模块的使用
Apr 14 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实现压缩图片尺寸并转为jpg格式的方法示例
2018/05/10 PHP
利用PHP扩展Xhprof分析项目性能实践教程
2018/09/05 PHP
PHP封装的数据库模型Model类完整示例【基于PDO】
2019/03/14 PHP
jQuery TextBox自动完成条
2009/07/22 Javascript
JavaScript 笔记二 Array和Date对象方法
2010/05/22 Javascript
js更优雅的兼容
2010/08/12 Javascript
Egret引擎开发指南之运行项目
2014/09/03 Javascript
jQuery实现提交按钮点击后变成正在处理字样并禁止点击的方法
2015/03/24 Javascript
js立即执行函数: (function ( ){})( ) 与 (function ( ){}( )) 有什么区别?
2015/11/18 Javascript
js表单元素checked、radio被选中的几种方法(详解)
2016/08/22 Javascript
echarts整合多个类似option的方法实例
2018/07/10 Javascript
layui中table表头样式修改方法
2018/08/15 Javascript
layui问题之模拟select点击事件的实例讲解
2018/08/15 Javascript
详解如何在Node.js的httpServer中接收前端发送的arraybuffer数据
2018/11/11 Javascript
layui关闭弹窗后刷新主页面和当前更改项的例子
2019/09/06 Javascript
微信小程序swiper使用网络图片不显示问题解决
2019/12/13 Javascript
Python爬取读者并制作成PDF
2015/03/10 Python
python基于右递归解决八皇后问题的方法
2015/05/25 Python
python实现指定字符串补全空格、前面填充0的方法
2018/11/16 Python
Python 带有参数的装饰器实例代码详解
2018/12/06 Python
python下载微信公众号相关文章
2019/02/26 Python
Pycharm使用之设置代码字体大小和颜色主题的教程
2019/07/12 Python
python实现MySQL指定表增量同步数据到clickhouse的脚本
2021/02/26 Python
mui几种页面跳转方式对比总结概括
2017/08/18 HTML / CSS
俄罗斯旅游网站:Tripadvisor俄罗斯
2017/03/21 全球购物
Desigual英国官网:在线购买原创服装
2018/03/09 全球购物
雅诗兰黛澳大利亚官网:Estée Lauder澳大利亚
2019/05/31 全球购物
POS解决方案:MUNBYN(热敏打印机、条形码扫描仪)
2020/06/09 全球购物
美国沃尔玛网上超市:Walmart
2020/08/14 全球购物
文明寝室标语
2014/06/13 职场文书
2014年社区国庆节活动方案
2014/09/16 职场文书
2014年流动人口工作总结
2014/11/26 职场文书
2014年学校教学工作总结
2014/12/06 职场文书
读《庄子》有感:美而不自知
2019/11/06 职场文书
CSS 新特性 contain控制页面的重绘与重排问题
2021/04/30 HTML / CSS
基于PyQt5制作一个群发邮件工具
2022/04/08 Python