侧边栏壁纸
  • 累计撰写 123 篇文章
  • 累计创建 27 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

闭包和装饰器

梁来福
2023-03-18 / 0 评论 / 0 点赞 / 0 阅读 / 8579 字
温馨提示:
本文最后更新于 2024-05-06,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

闭包

介绍

image.png

定义

image.png

构成条件

image.png

代码示例

# 外部函数
def func_out():
    num1 = 10

    # 内部函数
    def func_inner(num2):
        result = num1 + num2
        print("结果:", result)

    # 外部函数返回内部函数
    return func_inner


# 获取闭包对象 (new_func就是闭包)
# 这里new_func = func_inner
new_func = func_out()

# 执行闭包
new_func(1)
new_func(10)

运行结果

结果: 11
结果: 20

闭包执行结果说明

image.png

闭包的作用

image.png

闭包的使用

案例

image.png

实现步骤说明

image.png

代码实现

示例

# 外部函数:接收姓名参数
def config_name(name):

    # 内部函数:保存外部函数的参数,并且完成数据显示的组成
    def inner(msg):
        print(name + ":" + msg)

    # 查看内存地址是否一样
    print(id(inner))

    # 外部函数返回内部函数
    return inner


# 创建张三闭包实例(对象)
zhangsan = config_name("张三")
# 创建李四闭包实例(对象)
lisi = config_name("李四")

# 执行闭包
zhangsan("李四,我们一起开黑吧!")
lisi("我不跟你玩,你太菜了")
zhangsan("我TM")
lisi("你TM")

输出

4369971088
4369971232
张三:李四,我们一起开黑吧!
李四:我不跟你玩,你太菜了
张三:我TM
李四:你TM

修改闭包内使用的外部变量

错误代码

示例

# 外部函数
def func_out():
    num1 = 10

    # 内部函数
    def func_inner():
        # 在闭包内修改外部函数的变量
        num1 = 20  # 本意上是修改外部函数变量,其实是在闭包内定义了一个局部变量

        result = num1 + 10
        print("结果:", result)

    print("修改前的外部变量:", num1)
    func_inner()
    print("修改后的外部变量:", num1)

    # 外部函数返回内部函数
    return func_inner


# 获取闭包对象 (new_func就是闭包)
# 这里new_func = func_inner
new_func = func_out()

# 执行闭包
new_func()

输出

修改前的外部变量: 10
结果: 30
修改后的外部变量: 10
结果: 30

正确代码

示例

# 外部函数
def func_out():
    num1 = 10

    # 内部函数
    def func_inner():
        # 在闭包内修改外部函数的变量
        # 闭包内修改外部函数变量使用nonlocal关键字
        nonlocal num1
        num1 = 20
        result = num1 + 10
        print("结果:", result)

    print("修改前的外部变量:", num1)
    func_inner()
    print("修改后的外部变量:", num1)

    # 外部函数返回内部函数
    return func_inner


# 获取闭包对象 (new_func就是闭包)
# 这里new_func = func_inner
new_func = func_out()

# 执行闭包
new_func()

输出

修改前的外部变量: 10
结果: 30
修改后的外部变量: 20
结果: 30

装饰器

定义

给已有函数增加额外功能的函数,本质上就是一个闭包函数

功能特点

  • 不修改已有函数的源代码
  • 不修改已有函数的调用方式
  • 给已有函数增加额外的功能

代码

示例

# 定义装饰器
def decorator(func):
    def inner():
        print("已添加登录验证")
        func()
    return inner


def comment():
    print("发表评论")


# 调用装饰器对已有函数进行装饰:comment=inner
comment = decorator(comment)
comment()

输出结果

已添加登录验证
发表评论

代码说明

image.png

装饰器的语法糖

介绍

image.png

代码

# 定义装饰器
def decorator(func):
    #  装饰器的执行时机:当当前模块加载完成以后,装饰器就会立即执行,对已有函数进行装饰
    print("装饰器执行了")
  
    def inner():
        print("已添加登录验证")
        func()
    return inner


# 装饰器的语法糖写法:@装饰器名称
@decorator  # comment = decorator(comment)
def comment():
    print("发表评论")


# 调用装饰器对已有函数进行装饰:comment=inner
comment()

执行结果

已添加登录验证
发表评论

说明

image.png

小结

image.png

装饰器的使用

使用场景

1、函数执行时间的统计

代码示例

import time


# 定义装饰器
def decorator(func):
    def inner():
        # 获取时间:距离1970-1-1-00:00:00的时间差
        begin_time = time.time()
        func()
        end_time = time.time()

        result = end_time - begin_time
        print("函数执行完成耗时:", result, "秒")

    return inner


@decorator  # work = decorator(work),work = inner
def work():
    for i in range(100):
        print(i)


work()

输出

......

98
99
函数执行完成耗时: 0.00038695335388183594 秒

2、输出日志信息

通用的装饰器

带有参数的函数

代码示例

def decorator(func):
    # 使用装饰器装饰已有函数的时候,内部函数的类型和要装饰的已有函数的类型保持一致
    def inner(a, b):
        print("正在执行加法计算...")
        func(a, b)

    return inner


@decorator
def add_num(num1, num2):
    result = num1 + num2
    print("计算结果是:", result)


add_num(2, 3)

输出

正在执行加法计算...
计算结果是: 5

带有参数有返回值的函数

代码示例

# 定义装饰器
def decorator(func):
    # 使用装饰器装饰已有函数的时候,内部函数的类型和要装饰的已有函数的类型保持一致
    def inner(a, b):
        print("正在执行加法计算...")
        add_num = func(a, b)
        return add_num
  
    return inner


@decorator
def add_num(num1, num2):
    result = num1 + num2
    return result


result = add_num(2, 3)
print("结果为:", result)

输出

正在执行加法计算...
结果为: 5

带有不定长参数和返回值的函数

代码示例

# 定义装饰器
# 该装饰器还可以称为是通用的装饰器
def decorator(func):
    # 使用装饰器装饰已有函数的时候,内部函数的类型和要装饰的已有函数的类型保持一致
    def inner(*args, **kwargs):
        # 在内部函数对已有函数进行装饰
        print("正在执行加法计算...")
        # *args:把元祖里面的每一个元素按照位置参数的方式进行传参
        # **kwargs:把字典里面的每一个键值对按照关键字的方式进行传参
        # 这里对元祖和字典进行拆包,仅限于结合不定长参数的函数使用
        add_num = func(*args, **kwargs)
        return add_num

    return inner


# 用装饰器语法糖方式装饰带有参数的函数
@decorator  # add_num=decorator(add_num),add_num=inner
def add_num(*args, **kwargs):
    result = 0
    # args: 元祖类型
    # kwargs:字典类型
    for value in args:
        result += value
    for value in kwargs.values():
        result += value

    return result


result = add_num(2, 2)
print("结果为:", result)

输出

正在执行加法计算...
结果为: 4

多个装饰器的使用

代码示例

def make_div(func):
    print("make_div装饰器执行了")

    def inner():
        result = "<来福>" + func() + "</来福>"
        return result

    return inner


def make_p(func):
    print("make_p装饰器执行了")

    def inner():
        result = "<p>" + func() + "</p>"
        return result

    return inner


@make_div
@make_p
def content():
    return "python"


result = content()
print(result)

输出

make_p装饰器执行了
make_div装饰器执行了
<来福>

python

</来福>

带有参数的装饰器

代码示例

def return_decorator(flag):
    # 装饰器只能接收一个参数并且是函数类型
    def decorator(func):
        def inner(a, b):
            if flag == "+":
                print("正在努力执行加法计算中...")
            if flag == "-":
                print("正在努力执行减法计算中...")
            func(a, b)
        return inner
    # 当调用函数的时候可以返回一个装饰器decorator
    return decorator


# 加法计算
@return_decorator("+")
def add_num(a, b):
    result = a + b
    print(result)


# 减法计算
@return_decorator("-")
def sub_num(a, b):
    result = a - b
    print(result)


add_num(2, 3)
sub_num(1, 4)

输出

正在努力执行加法计算中...
5
正在努力执行减法计算中...
-3

小结

image.png

类装饰器

介绍

类装饰器就是通过定义一个类来装饰函数

代码示例

class Mylaifu(object):
    def __init__(self, func):
        self.__func = func

    # 实现__call__方法,让对象变成可调用对象,能够像函数一样使用
    def __call__(self, *args, **kwargs):
        # 对已有函数进行封装
        print("刘来福")
        self.__func()


@Mylaifu
def show():
    print("梁来福")


show()

输出

刘来福
梁来福

0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin
博主关闭了所有页面的评论