装饰器模式,重点在于装饰。装饰的核心仍旧是被装饰对象。

类比于Java编程的时候的包装模式,是同样的道理。虽然概念上稍有不同但是原理上还是比较相近的。下面我就来谈一谈我对Python的装饰器的学习的一点心得吧。


关于作用域

Python作用域 体现在LEGB中:

  • L:local 函数内部
  • E: enclosing 函数内部和内置函数之间
  • G:global 全局性质,有命名空间的限制
  • B:build-in 内置函数,由python解释器管理

学过编程的人一眼就可以看得出来大致是什么意思,所以这里不再叙述。


关于闭包

关键在于理解Python中闭包的概念。说白了,闭包就是函数里面又定义了函数,这就是闭包了。(呵呵,断章取义一下。可能说法不恰当)。如下:

def func1():
    print 'func1 is running'
    def in_func1():
        print 'in_func1 is running'
        return in_func1
    print 'over'

简单的一个闭包的实现,就差不多是这个样子的。我们需要注意的就是要将内部函数当成一个对象来返回(Python中函数其实就是一个对象,我们可以通过type来进行验证)。

这段代码执行的流程是先执行func1,然后执行func2,并且将func2作为一个属性返回给func1.这样我们可以再次的得到func2的内容。这就是闭包!


关于装饰器

类比Java中那么多的模式,比如ServletRequest被装饰成了HttpServletRequest。Python中也有很多这样被装饰的例子。如CookieJar被装饰成了MozillaCookieJar等等。实现的功能就是被装饰对象的功能得到了增强,完成的效果也大大大的比未装饰之前好了。这就是装饰的好处。

下面就来看一看Python中怎么来实现装饰器吧。

核心:借助于@符号,即可。

def bar():
    print 'Bar'

@bar
def foo():
    print "foo"
# 其等价于:
def foo():
    print "foo"
foo = bar(foo)

代码执行的流程:

先执行@对象,也就是一个函数。其返回值就是一个内置函数,只不过这个内置函数是得到了装饰的被装饰对象(这里是foo函数),我们可以理解为:

装饰器,其本身接收一个函数对象作为参数,然后做一些工作后,返回接收的参数,供外界调用。

下面看一个实例:

import time

def function_performance_statistics(trace_this=True):
    if trace_this:
       def performace_statistics_delegate(func):
            def counter(*args, **kwargs):
                start = time.clock()
                func(*args, **kwargs)
                end =time.clock()
                print 'used time: %d' % (end - start, )
            return counter
    else:
       def performace_statistics_delegate(func):
            return func
    return performace_statistics_delegate

@function_performance_statistics(True)
def add(x, y):
    time.sleep(3)
    print 'add result: %d' % (x + y,)

@function_performance_statistics(False)
def mul(x, y=1):
    print 'mul result: %d' % (x * y,)

add(1, 1)
mul(10)
上述代码想要实现一个性能分析器,并接收一个参数,来控制性能分析器是否生效,其运行效果如下所示:
add result: 2
used time: 0
mul result: 10
上述代码中装饰器的调用等价于:
add = function_performance_statistics(True)(add(1, 1))
mul = function_performance_statistics(False)(mul(10))

总结

Python装饰器的核心就是装饰,实质就是被装饰函数性能的增强。

Python装饰器模式学习总结的更多相关文章

  1. python装饰器的学习笔记

    此博文是我对装饰器的一些理解,如果有错误欢迎及时留言,我会第一时间向大家学习. 一.什么是装饰器 1.从字面意义来看: 是用来给函数装饰打扮的函数 2.理论上可以理解为: (1).不改变函数的运行方式 ...

  2. python 装饰器初步学习

    第一步 简单函数 ''' 简单的函数:调用两次''' def myfunc(): print ('myfunc() called.') myfunc() myfunc() 第二步 装饰器为调用函数提供 ...

  3. Python设计模式-装饰器模式

    装饰器模式 装饰器模式,动态地给一个对象添加一些额外的职责,就增加功能来说,装饰器模式比生成子类更为灵活. 代码示例 #coding:utf-8 #装饰器模式 class Beverage():   ...

  4. 《精通Python设计模式》学习结构型之装饰器模式

    这只是实现了Python的装饰器模式. 其实,python的原生的装饰器的应用比这个要强,要广的. ''' known = {0:0, 1:1} def fibonacci(n): assert(n ...

  5. Python 装饰器学习

    Python装饰器学习(九步入门)   这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方式. 第一步:最简单的函数,准备附加额外功能 1 2 3 4 5 6 7 8 # -*- c ...

  6. (转载)Python装饰器学习

    转载出处:http://www.cnblogs.com/rhcad/archive/2011/12/21/2295507.html 这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方 ...

  7. Python装饰器学习

    Python装饰器学习(九步入门)   这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方式. 第一步:最简单的函数,准备附加额外功能 ? 1 2 3 4 5 6 7 8 # -*- ...

  8. Python 装饰器学习心得

    最近打算重新开始记录自己的学习过程,于是就捡起被自己废弃了一年多的博客.这篇学习笔记主要是记录近来看的有关Python装饰器的东西. 0. 什么是装饰器? 本质上来说,装饰器其实就是一个特殊功能的函数 ...

  9. 【转】九步学习python装饰器

    本篇日志来自:http://www.cnblogs.com/rhcad/archive/2011/12/21/2295507.html 纯转,只字未改.只是为了学习一下装饰器.其实现在也是没有太看明白 ...

随机推荐

  1. hy 的惩罚

    [问题描述] hy 抄题解又被老师抓住了,现在老师把他叫到了办公室. 老师要 hy 和他 玩一个游戏.如果 hy 输了,老师就要把他开除信息组:  游戏分为 k 轮.在游戏开始之前,老师会将 n 个由 ...

  2. 洛谷mNOIP模拟赛Day2-入阵曲

    题目背景 pdf题面和大样例链接:http://pan.baidu.com/s/1cawM7c 密码:xgxv 丹青千秋酿,一醉解愁肠. 无悔少年枉,只愿壮志狂. 题目描述 小 F 很喜欢数学,但是到 ...

  3. 计蒜客NOIP2017提高组模拟赛(五)day2-成绩统计

    传送门 用hash,因为map的复杂度可能在这题中因为多一个log卡掉,但是hash不会 可能因为这个生成的随机数有循环的情况,不是完全均匀的 而且这题hash表的长度也可以开的很大 #include ...

  4. 【20170521校内模拟赛】热爱生活的小Z

    学长FallDream所出的模拟赛,个人感觉题目难度还是比较适中的,难度在提高+左右,可能比较接近弱省省选,总体来讲试题考查范围较广,个人认为还是很不错的. 所有试题如无特殊声明,开启-O2优化,时限 ...

  5. Divide by Zero 2017 and Codeforces Round #399 (Div. 1 + Div. 2, combined)

    C题卡了好久,A掉C题之后看到自己已经排在好后面说实话有点绝望,最后又过了两题,总算稳住了. AC:ABCDE Rank:191 Rating:2156+37->2193 A.Oath of t ...

  6. UVA 12161 Ironman Race in Treeland

    题目大意: 每一条边都有两个权值,val和路径长度d,要保证在val<=m 的条件下,求最长的d. 解题报告: 一开始想错了,后来发现还不如直接暴力点分,思想很套路.. 平时我们统计时,都会用合 ...

  7. bzoj3930[CQOI2015]选数 容斥原理

    3930: [CQOI2015]选数 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1383  Solved: 669[Submit][Status] ...

  8. [APIO2011]

    来自FallDream的博客,未经允许,请勿转载,谢谢. ------------------------------------------------------ A.[Apio2011]方格染色 ...

  9. 使用PL/SQL Developer连接远程DB(本机不安装Oracle客户端)

    本文内容亲测可行环境:    服务端:centos6.7 ,oracle 11g r2 ,动态注册,监听端口号:1521    用户端:win7 ,没有安装ORACLE及其客户端 准备文件:plsql ...

  10. Java高新技术第一篇:类加载器详解

    首先来了解一下字节码和class文件的区别: 我们知道,新建一个Java对象的时候,JVM要将这个对象对应的字节码加载到内存中,这个字节码的原始信息存放在classpath(就是我们新建Java工程的 ...