Python中函数有一个装饰器的概念,今天,看核心编程中的函数一章的时候接触到了这个概念,炸一看来,讲的说明真实不好明白。于是写下本篇以示说明,提供给迷糊者。希望能对一些人起到一定的帮助

装饰器的语法以@开头,接着是装饰器要装饰的函数的申明等。

其实总体说起来,装饰器其实也就是一个函数,一个用来包装函数的函数,装饰器在函数申明完成的时候被调用,调用之后申明的函数被换成一个被装饰器装饰过后的函数。装饰器分为无参装饰和有参装饰

无参装饰很简单

定义方法如下:

比如先定义一个装饰方法:

1
2
3
4
5
6
def FirstDeco(func):
   print '第一个装饰器'
   return func
@FirstDeco
def test():
  print 'asdf'

申明完成之后显示(在shell里试一下就知道了)

>>>第一个装饰器

可见装饰器在函数定义完成的时候被触发

然后,咱们运行

>>>test

>>>asdf

多参装饰:

多参装饰复杂一点,多参装饰的时候,装饰函数先处理参数,再生成一个新的装饰器函数,然后对函数进行装饰

具体代码如下:

1
2
3
4
5
6
7
8
9
10
def deco(x):
    print '%s 开始新装饰'
    def newDeco(func):
        def test(a,b):
            print 'begin'
                returnv = func(a,b)
                print 'end'
                return returnv
        return test
    return newDeco

这里定义了一个装饰其函数deco,里面有一个参数x,这个时候,我们没有直接使用func作为装饰函数的参数,而是只用了参数x作为参数,之后定义一个新的装饰函数,newdeco,该函数才装饰

然后定义如下:

1
2
3
4
5
6
@deco(3)
def mytest(x,y):
     if x>y:
         print x
     else:
         print y

运行之后的结果为

>>>%s 开始新装饰 >>> mytest(3,4) begin 4 end

装饰方法的产生:

Python2.2通过增加静态方法和类方法扩展了Python的对象模型。但是当时没有提供一个简化的语法去定义static/class方法,只得在定义好的方法尾部去调用staticmethod()/classmethod()方法达到目的。例如:

1
2
3
4
class C:
   def meth (cls):
         
   meth = classmethod(meth)   # 使meth方法成为类方法

但是这样会造成一个问题:当一个方法比较长时,很容易忘记尾部的调用。为了简化这个操作一个新的语法被加了进来:方法装饰,以@开头后跟装饰方法 名,如@staticmethod/@classmethod,由此产生出decorator方法及decorator模式。现在我们可以这样写:

1
2
3
class C:
   @classmethod
   def meth (cls):

可以对一个方法应用多个装饰方法:

1
2
3
4
5
6
7
8
@A
@B
@C
def f ():
     
#等价于下面的形式,Python会按照应用次序依次调用装饰方法(最近的先调用)
def f():
= A(B(C(f)))

装饰方法解析:

每个decorator只是一个方法, 可以是自定义的或者内置的(如内置的@staticmethod/@classmethod)。decorator方法把要装饰的方法作为输入参数,在函数体内可以进行任意的操作(可以想象其中蕴含的威力强大,会有很多应用场景), 只要确保最后返回一个可执行的函数即可(可以是原来的输入参数函数, 或者是一个新函数)。decorator的作用对象可以是模块级的方法或者类方法。decorator根据应用时的参数个数不同分为两类:无参数 decorator,有参数decorator。下面分别介绍。

无参数decorator:

1
2
3
4
5
6
7
8
9
10
11
12
13
def deco(func):
    """无参数调用decorator声明时必须有一个参数,这个参数将接收要装饰的方法"""
    print "Enter decorator"     #进行额外操作
    func.attr = 'decorated'     #对函数进行操作,增加一个函数属性
    return func   #返回一个可调用对象(此例还是返回作为输入参数的方法)
                      #返回一个新函数时,新函数可以是一个全局方法或者decorator函数的内嵌函数,
                      #只要函数的签名和被装饰的函数相同
  
@deco
def MyFunc():   #应用@deco修饰的方法
    print "Enter MyFunc"
  
MyFunc()     #调用被装饰的函数

注意:当使用上述方法定义一个decorator方法时,函数体内的额外操作只在被装饰的函数首次调用时执行,如果要保证额外操作在每次调用被装饰的函数时都执行,需要换成如下的写法:

1
2
3
4
5
6
7
8
9
10
11
def deco(func):
    def replaceFunc():     #定义一个内嵌函数,此函数包装了被装饰的函数,并提供额外操作的代码
        print "Enter decorator"     #进行额外操作
        return func()    #产生对被装饰函数的调用
    return replaceFunc   #由于返回的是这个新的内嵌函数,所以确保额外操作每次调用得以运行
  
@deco
def MyFunc():   #应用@deco修饰的方法
    print "Enter MyFunc"
  
MyFunc()     #调用被装饰的函数

有参数decorator:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def decoWithArgs(arg):
    """由于有参数的decorator函数在调用时只会使用应用时的参数而不接收被装饰的函数做为参数,
       所以必须返回一个decorator函数, 由它对被装饰的函数进行封装处理"""
    def newDeco(func):    #定义一个新的decorator函数
        def replaceFunc():    #在decorator函数里面再定义一个内嵌函数,由它封装具体的操作
            print "Enter decorator"     #进行额外操作
            return func()    #对被装饰函数进行调用
        return replaceFunc
    return newDeco    #返回一个新的decorator函数
  
@decoWithArgs("demo")
def MyFunc():    #应用@decoWithArgs修饰的方法
    print "Enter MyFunc"
 
  Myfunc()    #调用被装饰的函数

当我们对某个方法应用了装饰方法后, 其实就改变了被装饰函数名称所引用的函数代码块入口点,使其重新指向了由装饰方法所返回的函数入口点。由此我们可以用decorator改变某个原有函数的功能,添加各种操作,或者完全改变原有实现。

python装饰器(整理版)的更多相关文章

  1. python 装饰器 一篇就能讲清楚

    装饰器一直是我们学习python难以理解并且纠结的问题,想要弄明白装饰器,必须理解一下函数式编程概念,并且对python中函数调用语法中的特性有所了解,使用装饰器非常简单,但是写装饰器却很复杂.为了讲 ...

  2. 转发对python装饰器的理解

    [Python] 对 Python 装饰器的理解的一些心得分享出来给大家参考   原文  http://blog.csdn.net/sxw3718401/article/details/3951958 ...

  3. Python—装饰器详解

    装饰器:(语法糖) 本质是函数,它是赋予函数新功能,但是不改变函数的源代码及调用方式   原则: 1.不能修改被装饰函数的源代码 2.不能修改被装饰函数的调用方式 3.函数的返回值也不变 这两点简而言 ...

  4. Python高级特性: 12步轻松搞定Python装饰器

    12步轻松搞定Python装饰器 通过 Python 装饰器实现DRY(不重复代码)原则:  http://python.jobbole.com/84151/   基本上一开始很难搞定python的装 ...

  5. (十)Python装饰器

    装饰器:本质就是函数,功能是为其他函数添加附加功能. 两个原则: 1.不修改被修饰函数的源代码 2.不修改被修饰函数的调用方式 一个栗子 def test(): res = 0 for i in ra ...

  6. 【低门槛 手把手】python 装饰器(Decorators)原理说明

    本文目的是由浅入深地介绍python装饰器原理 装饰器(Decorators)是 Python 的一个重要部分 其功能是,在不修改原函数(类)定义代码的情况下,增加新的功能 为了理解和实现装饰器,我们 ...

  7. 关于python装饰器

    关于python装饰器,不是系统的介绍,只是说一下某些问题 1 首先了解变量作用于非常重要 2 其次要了解闭包 def logger(func): def inner(*args, **kwargs) ...

  8. python装饰器通俗易懂的解释!

    1.python装饰器 刚刚接触python的装饰器,简直懵逼了,直接不懂什么意思啊有木有,自己都忘了走了多少遍Debug,查了多少遍资料,猜有点点开始明白了.总结了一下解释得比较好的,通俗易懂的来说 ...

  9. Python 装饰器学习

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

  10. python 装饰器修改调整函数参数

    简单记录一下利用python装饰器来调整函数的方法.现在有个需求:参数line范围为1-16,要求把9-16的范围转化为1-8,即9对应1,10对应2,...,16对应8. 下面是例子: def fo ...

随机推荐

  1. Windows Server 2012 搭建DHCP及远程路由访问

    1.1    基础环境信息 1.2    DHCP与远程访问服务器角色安装 1.服务器管理器—>仪表板—>添加角色和功能,出现添加角色和功能向导,点击下一步 2.选择安装类型为基于角色或基 ...

  2. python实现排序之冒泡排序

    冒泡排序:是将一串无需的数字,排列成有序的.通过相邻的两个数作比较,大的往后移,经过反复的比较,最后得出一串有序的数列. 那么用代码该如何实现? 其实这个问题的思路就是判断每相邻的两个数,进行大小比较 ...

  3. Linux下 VI 编辑器操作

    VI编辑器的三种模式:命令模式.输入模式.末行模式. 1.命令模式:vi启动后默认进入的是命令模式,从这个模式使用命令可以切换到另外两种模式,同时无论在何种模式下,[Esc]键都可以回到命令模式.在命 ...

  4. Python全栈day 04

    Python全栈day 04 一.解释器/编译器 补充:编译型语言和解释型语言? # 编译型:代码写完后,编译器将其变成成另外一个文件,然后交给计算机执行. c c++,c# ,java # 解释型: ...

  5. POJ 3662 (二分+SPFA

    Telephone Lines Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8856   Accepted: 3211 D ...

  6. Codeforces Round 97B 点分治

    B. Superset time limit per test 2 seconds memory limit per test 256 megabytes input standard input o ...

  7. 9 与python2交互

    1.创建外键 # 创建room表 mysql> create table rooms(id )); Query OK, rows affected (0.01 sec) #创建学生表 mysql ...

  8. 2753: [SCOI2012]滑雪与时间胶囊

    2753: [SCOI2012]滑雪与时间胶囊 Time Limit: 50 Sec  Memory Limit: 128 MBSubmit: 2633  Solved: 910 Descriptio ...

  9. 《Cracking the Coding Interview》——第11章:排序和搜索——题目2

    2014-03-21 20:49 题目:设计一种排序算法,使得anagram排在一起. 解法:自定义一个comparator,使用额外的空间来统计字母个数,然后比较字母个数. 代码: // 11.2 ...

  10. webstrom11 vue插件配置

    直接上图 1. 安装vue插件 2.添加模板 3.指定模板类型 最新的是插件 是 vue.js 创建完 Vue File 文件后 需要在 下面这里关联一下