Erlo

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

时间:2019-08-15 12:02   阅读:148次   来源:博客园页面报错

点赞

首先我们应该知道一件事:函数的定义域跟定义位置有关系,而跟调用位置没有关系。
闭包函数:
定义:内层函数对外层函数而非全局变量的引用,就叫做闭包函数
闭包会一直存在在内存中,不会因为函数执行结束而被释放
先看个例子:
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

那么到此处我们就已经掌握了装饰器的内容,上边是一个框架
下一篇:python基础--函数作用域

评论留言

还没有评论留言,赶紧来抢楼吧~~

Erlo大厅()

* 这里是“吐槽厅”,所有人可看,只保留当天信息。

  • Erlo.vip2019-09-21 19:09:57Hello、欢迎使用吐槽厅,这里是个吐槽的地方。
  • 首页 笔记分享 案例展示 ERLO 搜索
    鼠标试试
    返回顶部