python中的@装饰器

先看一段代码

#!/usr/bin/python

def test(func):
    func()

@test
def fun():
    print "call fun"

上面的代码没有main()调用或者直接的函数调用,结果还是会输出

call fun

@修饰符有点像函数指针,python解释器发现执行的时候如果碰到@修饰的函数,首先就解析它,找到它对应的函数进行调用,并且会把@修饰下面一行的函数作为一个函数指针传入它对应的函数。有点绕口,这里说的“它对应的函数”就是名字是一样的。下面说下之前代码的解析流程

  1. python解释器发现@test,就去调用test函数
  2. test函数调用预先要指定一个参数,传入的就是@test下面修饰的函数,也就是fun()
  3. test()函数执行,调用fun(),fun()打印“call fun”

再看一段代码

#!/usr/bin/python

def test(func):
    func()
    print "call test over"

def main():
    @test
    def fun():
        print "call fun"
#main()

这样调用的话就不会调用test,只有当main函数调用的时候才会进入到main函数,然后调用test。
来看看正规的用法


def t(func):
    print "in t"
    def _a():
        print "in a"
        return func()
    print "call t over"
    return _a

@t
def hello():
    print "hello"

hello()

输出

in t
call t over
in a
hello

运行流程

  1. 执行hello(),发现有@修饰符,把hello()作为函数指针传入@修饰的函数t()
  2. t()函数执行到return _a,这时候会去调用_a()
  3. _a()函数执行func(),这里的func()就是之前传入了hello()
  4. 执行hello()函数的打印

应用场景:测试函数运行时间

from time import clock

def get_run_time(func):
    def _a():
        start = clock()
        func()
        end = clock()
        print end-start
    return _a

@get_run_time
def hello():
    print "hello\n"

hello()

注意一定要写成这样闭包的形式

### 如何传参数

def t(func):
    print "in t"
    def _a(* args, ** kwds):
        print "in a"
        return func(* args, ** kwds)
    print "call t over"
    return _a

@t
def hello(v):
    print "hello", v

hello("world")

更多用法

[http://www.cnblogs.com/rhcad/archive/2011/12/21/2295507.html](http://www.cnblogs.com/rhcad/archive/2011/12/21/2295507.html)

标签:Python