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实现给字典添加条目的方法
Sep 25 Python
Python中isnumeric()方法的使用简介
May 19 Python
Python中处理字符串的相关的len()方法的使用简介
May 19 Python
利用python生成一个导出数据库的bat脚本文件的方法
Dec 30 Python
在Python web中实现验证码图片代码分享
Nov 09 Python
高质量Python代码编写的5个优化技巧
Nov 16 Python
基于python批量处理dat文件及科学计算方法详解
May 08 Python
python的常见矩阵运算(小结)
Aug 07 Python
QML使用Python的函数过程解析
Sep 26 Python
Python+Selenium+phantomjs实现网页模拟登录和截图功能(windows环境)
Dec 11 Python
Python猴子补丁知识点总结
Jan 05 Python
Python + opencv对拍照得到的图片进行背景去除的实现方法
Nov 18 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用户注册时常用的检验函数实例总结
2014/12/22 PHP
编写PHP程序检查字符串中的中文字符个数的实例分享
2016/03/17 PHP
兼容IE和Firefox火狐的上下、左右循环无间断滚动JS代码
2013/04/19 Javascript
jQuery页面加载初始化常用的三种方法
2014/06/04 Javascript
js+div+css下拉导航菜单完整代码分享
2016/12/28 Javascript
使用cropper.js裁剪头像的实例代码
2017/09/29 Javascript
vue项目搭建以及全家桶的使用详细教程(小结)
2018/12/19 Javascript
jQuery实现动态生成年月日级联下拉列表示例
2019/05/11 jQuery
VsCode里的Vue模板的实现
2020/08/12 Javascript
vue实现表格合并功能
2020/12/01 Vue.js
[01:43]深扒TI7聊天轮盘语音出处4
2017/05/11 DOTA
[04:14]从西雅图到上海——玩家自制DOTA2主题歌曲应援TI9
2019/07/11 DOTA
零基础写python爬虫之使用urllib2组件抓取网页内容
2014/11/04 Python
Python 登录网站详解及实例
2017/04/11 Python
Python实现多线程抓取网页功能实例详解
2017/06/08 Python
django表单实现下拉框的示例讲解
2018/05/29 Python
Python3多目标赋值及共享引用注意事项
2019/05/27 Python
python中selenium操作下拉滚动条的几种方法汇总
2019/07/14 Python
基于Python实现视频的人脸融合功能
2020/06/12 Python
使用Keras实现Tensor的相乘和相加代码
2020/06/18 Python
基于Tensorflow读取MNIST数据集时网络超时的解决方式
2020/06/22 Python
Django正则URL匹配实现流程解析
2020/11/13 Python
Python 爬虫批量爬取网页图片保存到本地的实现代码
2020/12/24 Python
美国受欢迎的眼影品牌:BH Cosmetics
2016/10/25 全球购物
德国网上花店:Valentins
2018/08/15 全球购物
SQL Server面试题
2013/04/04 面试题
餐厅经理岗位职责范本
2014/02/17 职场文书
政法学院毕业生求职信
2014/02/28 职场文书
2014年公司植树节活动方案
2014/03/04 职场文书
办公室班子四风问题对照检查材料
2014/10/04 职场文书
公务员检讨书
2014/11/01 职场文书
2014年仓库管理工作总结
2014/12/17 职场文书
2014年度考核工作总结
2014/12/24 职场文书
大学军训心得体会800字
2016/01/11 职场文书
2016中学教师读书心得体会
2016/01/13 职场文书
Html5生成验证码的示例代码
2021/05/10 Javascript