python中decorator

先讲一下python中的@符号

看下面代码

@f
@f2
    def fun(args, args2, args3, args4, ……):
        pass

上面代码相当于

def fun(args, args2, args3, args4, ……):
    pass
fun = fun(f2(fun))

 

def now():
    print('2016-06-03')
n = now
n2 = now()
n2 #2016-06-03
n() #2016-06-03

#函数对象有一个name属性,可以拿到函数的名字
print(n.__name__) #n这个变量指向的函数名为now,输出结果为now

def log(func):
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper
@log
def now():
    print('2016-06-03')
now()

#如果decorator本身需要传入参数,那就要编写一个返回decorator的高阶函数,比如自定义log的文本:
def log(text):
    def decorator(func):
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)
        return wrapper
    return decorator
@log('rain:')
def now():
    print('2016-06-03')
now()
#但是像上面那样优化,装饰后的函数的__name__已经从now变成了wrapper
print(now.__name__) #可以看到now这个名字已经被改成了wrapper

#为了防止依赖于签名的那些函数执行时出错,要把原来函数的__name__复制到wrapper中
import functools
def log(func):
    @functools.wraps(func)
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw) #注意这里返回的只是一个函数名,并没有传入参数
    return wrapper

@log #注意这里的也应该是一个函数名,如果看到传入某个参数的函数,那这个函数的返回值是一个函数
def ff():
    print('fun is running……')
ff() #只有编写函数之前加上@log,调用这个函数的时候才会直接调用log(ff())

import functools
#针对带参数的decorator
def log(text):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__)) #这里的格式,牢记牢记牢记,别出错了
            return func(*args, **kw)
        return wrapper
@log('rain:')
def func():
    print('i love rain')

 

posted on 2016-06-03 17:52  张明明_1  阅读(168)  评论(0编辑  收藏  举报

导航