Python 闭包函数和装饰器

闭包函数定义:

  • 基于嵌套函数
  • 如果在一个内部函数里,对在外部作用域(嵌套变量)的变量进行引用,那么内部函数就被认为是闭包函数。
    • Python 变量作用域 LEGB,具体参考 Python 变量作用域章节
  • 闭包中外部函数返回的不是一个具体的值,而是一个函数。一般情况下,返回的函数会赋值给一个变量,这个变量可以在后面被继续执行调用。
复制代码
def outer():
    x = 10
    def inner():  # 条件一:inner这是一个内部函数
        print(x)    # 条件二:引用外包环境的一个变量(但不是全局变量)
    return inner    # 结果:inner是一个闭包函数

f = outer()
f()

# 结果:10
复制代码

 装饰器的定义:

  • 它是一种函数的函数,因为装饰器传入的参数就是一个函数,然后通过实现各种功能来对这个函数的功能进行增强。

在哪里用装饰器:

  • 装饰器最大的优势是用于解决重复性的操作,其主要使用的场景有如下几个:
    • 计算函数运行时间  
    • 给函数打日志  
    • 类型检查  
  • 如下实例,我需要实现一个打印出函数 fun_one/fun_two/fun_three 中代码 sleep 的执行时间,这么写的话虽然功能可以实现,但是代码的冗余程度非常大
复制代码
from time import time, sleep
​
def fun_one():
    start = time()
    sleep(1)
    end = time()
    cost_time = end - start
    print("func one run time {}".format(cost_time))
    
def fun_two():
    start = time()
    sleep(1)
    end = time()
    cost_time = end - start
    print("func two run time {}".format(cost_time))
    
def fun_three():
    start = time()
    sleep(1)
    end = time()
    cost_time = end - start
    print("func three run time {}".format(cost_time))
复制代码
  • 使用装饰器的方法简化后如下
复制代码
def run_time(func):
    def wrapper():    # 此时的 wrapper 就是一个闭包函数
        start = time()
        func()                  # 函数在这里运行
        end = time()
        cost_time = end - start
        print("func run time {}".format(cost_time))
    return wrapper
​
@run_time    # 这里的装饰器会将函数名称 fun_one 传入到 上面的 run_time 函数中,从而执行   
def fun_one():
    sleep(1)
    
@run_time
def fun_two():
    sleep(1)
    
@run_time
def fun_three():
    sleep(1)
复制代码
  • 在功能函数中加上参数 
复制代码
from time import time, sleep

def run_time(func):
    def wrapper(a, b):    # 此时的 wrapper 就是一个闭包函数
        start = time()
        func(a, b)                  # 函数在这里运行
        end = time()
        cost_time = end - start
        print("func run time {}".format(cost_time))
    return wrapper

@run_time    # 这里的装饰器会将函数名称 fun_one 传入到 上面的 run_time 函数中,从而执行,fun_one = run_time(fun_one)
def fun_one(a, b):
    print(a)
    print(b)
    sleep(1)

fun_one("hello", "world")
复制代码
  • 带参数的装饰器
复制代码
from time import time, sleep

def logger(msg):   # 在此处多加一个装饰器参数
    def run_time(func):
        def wrapper(*args, **kwargs):
            start = time()
            func(args, kwargs)
            end = time()
            cost_time = end - start
            print("func_{} run time {}".format(msg, cost_time))
        return wrapper
    return run_time


@logger(msg="One")
def fun_one(a, b):
    print(a + b)
    sleep(1)


@logger(msg="Two")
def fun_two(a, b):
    print(a + b)
    sleep(1)

fun_one(1, 2)
fun_two(3, 4)

# 结果如下:
# 3
# func_One run time 1.0086338520050049
# 7
# func_Two run time 1.0099050998687744
复制代码

 

posted @   一个老宅男  阅读(32)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
历史上的今天:
2019-10-31 python(random 模块)
点击右上角即可分享
微信分享提示