python装饰器

  定义了一个函数,想在运行时动态增加功能,又不想改动函数本身的代码,这就是所谓的装饰器

例如:

希望对下列函数调用增加log功能,打印出函数调用:

def f1(x):
    return x*2
def f2():
    return x*x
def f3():
    return x*x*x

第一种方法,直接修改原函数:

def f1(x):
    print 'call f1()'
    return x*2
def f2():
    print'call f2()'
    return x*x
def f3():
    print 'cal f3()'
    return x*x*x

第二种方法,利用高阶函数:

def f1(x):
    return x*2
def new_fn(f):#装饰器函数
    def fn(x):
        print 'call' +f.__name__+'()'   #__name__为函数对象的属性
        return f(x)
    return fn

那我们如何调用装饰器了

第一种方法:

g1 = new_fn(f1)
print g1(5)

第二种方法,f1的原始定义函数被隐藏:

f1 =new_fn(f1)
print f1(5)

python内置的@语法就是为了简化装饰器调用:

@new_fn
def f1(x):
    return x*2

这段的代码就相对于是如下的代码的简写:

首先定义f1函数,然后通过new_fn这个高阶函数返回了一个新的函数并且这个新的函数并赋值给了f1,原有的f1函数就被彻底的隐藏。

def f1(x):
    return x*2
f1 = new_fn(f1)

装饰器可以极大的简化代码,避免每个函数编写重复性代码,并且装饰器可以打印日志:@long,检查性能:@performance,数据事务:@transaction,url路由:@post('/register')

完整示例:

def deco(func):
    def _deco(*args, **kwargs):
        print("before %s called." % func.__name__)
        ret = func(*args, **kwargs)
        print("  after %s called. result: %s" % (func.__name__, ret))
        return ret
    return _deco
 
@deco
def myfunc(a, b):
    print(" myfunc(%s,%s) called." % (a, b))
    return a+b
 
@deco
def myfunc2(a, b, c):
    print(" myfunc2(%s,%s,%s) called." % (a, b, c))
    return a+b+c
 
myfunc(1, 2)
myfunc(3, 4)
myfunc2(1, 2, 3)
myfunc2(3, 4, 5)

结果:

before myfunc called.
 myfunc(1,2) called.
  after myfunc called. result: 3
before myfunc called.
 myfunc(3,4) called.
  after myfunc called. result: 7
before myfunc2 called.
 myfunc2(1,2,3) called.
  after myfunc2 called. result: 6
before myfunc2 called.
 myfunc2(3,4,5) called.
  after myfunc2 called. result: 12

 

posted @ 2016-12-03 15:33  子非鱼smile  阅读(270)  评论(0编辑  收藏  举报