python基础-装饰器

什么是装饰器

# 概念:就是接受一个函数不改变里面的代码,进行包裹,然后返回函数的一个工具;不改变原函数调用方法的,对原函数进行包裹附加功能的工具
# 原理:利用高阶函数可以接受函数作为参数,返回函数作为结果实现迭代器
# 功能:极大的简化代码,避免编写重复性代码函数
# 本质:高阶函数

# @装饰器名字:等价于 f = decorate(f)。
# *args-**kw:要让 @log 自适应任何参数定义的函数,可以利用Python的 *args 和 **kw,保证任意个数的参数总是能正常调用。


# 打印日志:@log
# 用户验证:@auth
# 检测性能:@performance
# 数据库事务:@transaction
# URL路由:@post('/register')

 

无参数装饰器:就是没有参数的装饰器,一般两层包裹

# 无参数装饰器,
# 由于decorator返回的新函数函数名已经不是'factorial',而是@log内部定义的'wrapper'。
# 这对于那些依赖函数名的代码就会失效。decorator还改变了函数的 __name__,__doc__等其它属性。
# 如果要让调用者看不出一个函数经过了@decorator的“改造”,就需要把原函数的一些属性复制到新函数中:
# Python内置的functools可以用来自动化完成这个“复制”的任务:
def log(f):
    def wrapper(*args,**kwargs):
        ret = f(*args,**kwargs)
        print("call "+f.__name__)
        return ret
    return wrapper
@log
def factorial(n):
    return reduce(lambda x,y:x*y,range(1,n+1))

result = factorial(3)
print('result',result)

f = log(factorial)(3)
print('f',f)



# 打印执行时间
import time
def performance(f):
    def wrapper(*args,**kwargs):
        start = time.time()
        ret = f(*args,**kwargs)
        end = time.time()
        print('call %s() in %f'%(f.__name__,end-start))
        return ret
    return wrapper

@performance
def factorial(n):
    return reduce(lambda x,y: x*y, range(1, n+1))

print(factorial(10))

  

有参装饰器:就是有参数的装饰器,一般三层包裹

# 有参数装饰器,三层函数
def log1(n):
    print(n*1000)
    def outer(f):
        def wrapper(*args,**kwargs):
            ret = f(*args,**kwargs)
            print("call "+f.__name__)
            return ret
        return wrapper
    return outer
@log1(8)
def factorial(n):
    return reduce(lambda x,y:x*y,range(1,n+1))



result = factorial(3)
print(result)

f = log1(8)(factorial)(3)
print(f)





# 内部返回函数名(参数),返回函数名,返回函数名
# 以下是返回的__name__
import time, functools

# 没有加@functools.wraps(f):
def performance(unit):
    def f(f):
        def wrapper(*args, **kwargs):
            t1 = time.time()
            ret = f(*args, **kwargs)
            t2 = time.time()
            if unit == 's':
                print("call %s() in %s" % (f.__name__, t2 - t1))
            else:
                print("call %s() in %s" % (f.__name__, 1000 * (t2 - t1)))
            return ret
        return wrapper
    return f
@performance('ms')
def factorial(n):
    return reduce(lambda x, y: x * y, range(1, n + 1))
print("没有加@functools.wraps(f):",factorial.__name__)


# 有加@functools.wraps(f):
def performance(unit):
    def f(f):
        @functools.wraps(f)
        def wrapper(*args, **kwargs):
            t1 = time.time()
            ret = f(*args, **kwargs)
            t2 = time.time()
            if unit == 's':
                print("call %s() in %s" % (f.__name__, t2 - t1))
            else:
                print("call %s() in %s" % (f.__name__, 1000 * (t2 - t1)))
            return ret
        return wrapper
    return f
@performance('ms')
def factorial(n):
    return reduce(lambda x, y: x * y, range(1, n + 1))
print("有加@functools.wraps(f):",factorial.__name__)
# 就是在里面的函数外加个@functools.wraps(函数名的参数名)

  

 如何使用两种:原函数和新装饰器函数

def outer(f):
    def wrapper(*args,**kwargs):
        ret=f(*args,**kwargs)
        print("hello2:",*args)
        return ret
    return wrapper


@outer
def foo(name):
    print("hello:",name)
foo("adamanter")




def wrapper(fn):
    def inner():
        print("wrapped")
        fn()
    inner.raw = fn
    return inner


@wrapper
def foo():
    print("go")

if __name__ == '__main__':
    # 被装饰的
    foo()
    print("--------")
    # 没被装饰的
    foo.raw()

  

 

posted @ 2017-09-08 17:09  Adamanter  阅读(100)  评论(0编辑  收藏  举报