欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

python基础--闭包函数和装饰器

程序员文章站 2022-03-20 16:52:51
首先我们应该知道一件事:函数的定义域跟定义位置有关系,而跟调用位置没有关系。闭包函数:定义:内层函数对外层函数而非全局变量的引用,就叫做闭包函数 闭包会一直存在在内存中,不会因为函数执行结束而被释放先看个例子: def outer(): num = 1 def inner(): nonlocal n ......
首先我们应该知道一件事:函数的定义域跟定义位置有关系,而跟调用位置没有关系。
闭包函数:
定义:内层函数对外层函数而非全局变量的引用,就叫做闭包函数
闭包会一直存在在内存中,不会因为函数执行结束而被释放
先看个例子:
def outer():
    num = 1
    def inner():
        nonlocal num
        num += 1
        print(num)
    return inner
a = outer() # 此时a为一个函数
a() # 2
a() # 3
a() # 4
num会一直存在,不会因为外层函数结束而释放。
这就是闭包函数,可以在任何地方调用
闭包的意义
意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,
这使得无论在何处调用,优先使用自己外层包裹的作用域

装饰器:闭包函数的一种应用场景
装饰器原则:1,不修改对象的源代码,2,不修改对象的调用方式,
目标:在遵循1,2的前提下,为被装饰对象添加上新的功能

假如我们有这样一个需求,测试一个函数所用的时间
import time
def function():
    time.sleep(1)
    print('函数执行')
start_time = time.time()
function()
end_time = time.time()
print("函数的执行时间%s" %(end_time  - start_time))
# 但此时多了几行代码,再次修改
def function():
    time.sleep(1)
    print('函数执行')
def timeer():
    start_time = time.time()
    function()
    end_time = time.time()
    print("函数的执行时间%s" % (end_time - start_time))
timeer()
# 我们要想也计算其他函数的时间怎么办?
def function1():
    time.sleep(1)
    print('函数执行')
def timeer(function):
    start_time = time.time()
    function()
    end_time = time.time()
    print("函数的执行时间%s" % (end_time - start_time))
timeer(function1)
# 又有了新的要求,我们想要在不改变原函数的调用方式来修改
# 可以用闭包来实现
def function2():
    time.sleep(1)
    print('函数执行')
def timeer(function):
    def inner():
        start_time = time.time()
        function()
        end_time = time.time()
        print("函数的执行时间%s" % (end_time - start_time))
    return inner
function2 = timeer(function2)
function2() #这样就可以在不修改函数调用方式的情况下增加功能
# python有一个语法糖的功能,例子如下
def timeer(function):
    def inner():
        start_time = time.time()
        function()
        end_time = time.time()
        print("函数的执行时间%s" % (end_time - start_time))
    return inner

@timeer
# 相当于:function2 = timeer(function2)
def function2():
    time.sleep(1)
    print('函数执行')
function2()
上述就是装饰器的基本方式
新的问题又来了,我们写的函数有参数怎么办呢?
我们直接给inner加上参数就好了啊
注意,此时参数应该怎么加,应该保证同时适用于有参数和无参数的函数
因为我们不知道函数有几个参数,所以应该用不定长参数
def timeer(function):
    def inner(*args,**kwargs):
        # 这样函数没有参数也可以用
        start_time = time.time()
        function(*args,**kwargs)
        end_time = time.time()
        print("函数的执行时间%s" % (end_time - start_time))
    return inner
@timeer
def function2():
    time.sleep(1)
    print('函数执行')
@timeer
def add_num(num1,num2):
    print(num1 + num2)
function2()
add_num(3,5)
不知道大家发现没有,我们还有一个问题没有解决,
对了,那就是函数的返回值的问题,我们怎么给有返回值的函数加装饰器呢?
我们从前面可以知道,我们加了装饰器,是会执行装饰器内部的inner函数
那么我们给inner函数加上返回值就好了啊,看代码:
def timeer(function):
    def inner(*args,**kwargs):
        # 这样函数没有参数也可以用
        start_time = time.time()
        res = function(*args,**kwargs)
        # 此处用一个变量来接受函数的返回值。
        end_time = time.time()
        print("函数的执行时间%s" % (end_time - start_time))
        # 函数的最后应该有返回值,而且这个返回值必须是function函数执行后的返回值,
        # 那么我们就知道该怎么写代码了,我们用一个变量来接受函数function执行后的返回值就好了啊
        return res
        # 在此处返回
    return inner
@timeer
def max_num(num1,num2):
    if num1 > num2:
        return num1
    else:
        return num2
print(max_num(3,5))
def outer(function):
    def inner(*args,**kwargs):
        # 函数执行前你想要做的
        res = function()
        # 函数执行后你想要做的
        return res
    return inner
那么到此处我们就已经掌握了装饰器的内容,上边是一个框架