2018-06-24-Python全栈开发day20-函数闭包与装饰器

主要是为了实现装饰器的功能

装饰器:对原函数进行修饰,不改变原函数的调用方法和代码,但是经过装饰之后,可以改变原函数的功能。

装饰器=高阶函数+闭包+函数嵌套

对于一个函数,实现装饰器功能的过程,。

原函数:

import time
def test():
    time.sleep(1)
    print('这个是原函数')

目的:对这个函数进行修饰,在进行调用的时候,可以显示这个函数运行了多长时间。

如果仅使用高阶函数,进行修改。

#仅使用高阶函数来实现
import time
def test():
    time.sleep(1)
    print('这个是原函数')
#对这个函数进行修饰,显示原函数运行的时间

def wrapper(func):
    start_time=time.time()
    func()
    end_time=time.time()
    shijian=end_time-start_time
    print('运行时间是%s' %shijian)
    return func
test=wrapper(test)
test()

运行结果会出现问题:

在运行test=wrapper(test)的时候,wrapper函数已经开始运行,然后再次运行test()的时候,原函数就会再运行一次,所以,就没有实现装饰器的功能。

2.在高阶函数的基础上加上闭包和嵌套

#仅使用高阶函数来实现
import time
def test():
    time.sleep(1)
    print('这个是原函数')
#对这个函数进行修饰,显示原函数运行的时间
def zhuangshiqi(func):
    def wrapper():
        start_time=time.time()
        func()
        end_time=time.time()
        shijian=end_time-start_time
        print('运行时间是%s' %shijian)

    return wrapper
test=zhuangshiqi(test)
test()

上面简单的实现了装饰器的功能。在test=zhuangsihqi()的时候,代码只是进行了: return wrapper这个动作,函数并没有运行,在test()的时候,函数才正式运行

和只使用高阶函数相比,使用了嵌套和闭包,这样的话,在给test传值的时候,函数就不会运行,影响原函数的功能。

3.对于有return的原函数进行修改

  

#仅使用高阶函数来实现
import time
def test():
    time.sleep(1)
    print('这个是原函数')
    return 'abc'
#对这个函数进行修饰,显示原函数运行的时间
def zhuangshiqi(func):
    def wrapper():
        start_time=time.time()
        a=func()
        end_time=time.time()
        shijian=end_time-start_time
        print('运行时间是%s' %shijian)
        return a
    return wrapper
test=zhuangshiqi(test)
test()
b=test()
print(b)

对于原函数,test来说,可以有无数种return,所以装饰器内,需要通过一个参数,来变化的接收test函数中的ruturn,然后在return回去,

4.对于原函数有参数的情况下

#仅使用高阶函数来实现
import time
def test(x,y):
    time.sleep(1)
    print('这个是原函数')
    return x+y
#对这个函数进行修饰,显示原函数运行的时间
def zhuangshiqi(func):
    def wrapper(*args,**kwargs):
        start_time=time.time()
        a=func(*args,**kwargs)
        end_time=time.time()
        shijian=end_time-start_time
        print('运行时间是%s' %shijian)
        return a
    return wrapper
test=zhuangshiqi(test)
test(3,5)
b=test(3,5)
print(b)

使用*args来接收除字典外的值,使用**kwargs来接收字典,这两个组合可以接收不定长的参数。

在自己的分析中,test=zhuangshiqi(test)的时候,其实就是把test当做一个参数,放入wrapper当中,所以wrapper的参数要和test的参数一样,在wrapper当中,func其实就是wrapper,所以参数也必须一样,其实就是把参数传过去

猜你喜欢

转载自www.cnblogs.com/hai125698/p/9221721.html