python中的装饰器(python基础学习)

函数作用域:

LEGB原则:L>E>G>B

L:local函数内部作用域

E:enclosing函数内部和内嵌函数之间

G:global全局作用域

B:bulid-in内置作用域

装饰器

实质:对闭包的使用,把一个函数当做参数然后返回一个替代版函数。

作用:帮助我们从函数中抽离出与函数功能本身无关的雷同可复用代码。

想要为一个函数添加附加功能,但是又不想动函数本身的代码。例如想要为函数添加log等功能。对原函数进行包装,新增一些操作。

def new_fn(f):
    """
    给原函数添加一个log信息
    :param f: 原函数
    :return: 原功能+新功能的新函数
    """
    def fn(x):
        print('call'+f.__name__+'()')   # 添加log信息
        return f(x)    # 调用原函数
    return fn

# 添加装饰器的语法:@装饰器 
@new_fn
def f(x):
    return x*x


print(f(2))

无参数的装饰器:

打印出累积函数的调用时间。

import time

def performance(f):
    def fn(*args,**kwargs):
        t1 = time.time()
        r = f(*args,**kwargs)
        t2 = time.time()
        print 'call %s() in %fs' %(f.__name__,(t2-t1))
        return r
    return fn
   
@performance
def factorial(n):
    return reduce(lambda x,y:x*y,range(1,n+1))
    
print factorial(10)

带参数的装饰器:

打印出累积函数的调用时间,可以选择以秒或者毫秒来显示。

import time

def performance(unit):
    def performance_decorator(f):
        def fn(*args,**kwargs):
            t1=time.time()
            r = f(*args,**kwargs)
            t2=time.time()
            t = (t2-t1)*1000 if unit=='ms' else (t2-t1)
            print 'call %s() in %f %s'%(f.__name__,t,unit)
            return r
        return fn
    return performance_decorator

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

print factorial(10)

装饰器performance中有3层嵌套。核心的装饰器代码是中间2层,最外层是为整个装饰器新增了参数。但是单独拿出中间2层执行会报错,因为内部函数引用了外部函数的局部变量unit,也就是之前讲的闭包。由此可见,闭包内的函数不能够拆开来当做普通函数单独执行。

经过装饰器装饰过的函数返回的新函数的函数名已经不是原函数的函数名factorial了,而是装饰器内部定义的函数名fn,这对于那些依赖函数名的代码来说就会失效。需要将原函数的一些属性特性复制到新函数中,如下所示:

import time

def performance(unit):
    def performance_decorator(f):
        def fn(*args,**kwargs):
            t1= time.time()
            r = f(*args,**kwargs)
            t2 = time.time()
            t =(t2-t1)*1000 if unit==ms else (t2-t1)
            print 'call %s() in %f %s'%(f.__name__,t,unit)
        fn.__name__ = f.__name__   # 复制原函数特性到新函数
        fn.__doc__ = f.__doc__     # 复制原函数特性到新函数
        return fn
        
    return performance_decorator
        

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

print factorial.__name__   
像上面一个一个复制,是不可能的,因此python提供了内置的functools来完成“复制”的工作。
import time, functools  # 导入模块

def performance(unit):
    def performance_decorator(f):
        @functools.wraps(f)   # 使用functools模块,给fn新增复制的功能。
        def fn(*args,**kwargs):
            t1= time.time()
            r = f(*args,**kwargs)
            t2 = time.time()
            t =(t2-t1)*1000 if unit==ms else (t2-t1)
            print 'call %s() in %f %s'%(f.__name__,t,unit)
            return r
        return fn
    return performance_decorator
        

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

print factorial.__name__  # factorial

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值