一文带你了解Python中的闭包和装饰器

闭包

当调用完函数后,函数内定义的变量就销毁了,但有时需要保存函数内的这个变量,并在这个变量的基础上完成一系列的操作 ,那怎么办呢?               答案就是使用闭包!

作用:

        闭包可以保存函数内的变量,而不会随着调用完函数而被销毁。

语法:

# 外部函数
def 外部函数名(外部参数):
    # 内部函数
    def 内部函数名(内部参数):
        ...[使用外部函数的变量]
    return 内部函数名

构成条件:

        ①有嵌套:在函数嵌套(函数里面再定义函数)的前提下;

        ②有引用:内部函数使用了外部函数的变量(还包括外部函数的参数);

        ③有返回:外部函数返回了内部函数名。

应用场景----累加器:

"""
累加器

nonlocal:
    外部函数的变量必须用nonlocal修饰,这样改变量才可以被内置函数修改
"""
# 1.定义外部函数
def func_outer():       # 有嵌套
    # 2.定义外部函数变量
    a = 100
    # 3.定义内部函数
    def func_inner():   # 有嵌套
        # 核心细节:外部函数的变量必须用nonlocal修饰,这样改变量才可以被内置函数修改
        nonlocal a
        # 累加器动作 然后输出
        a = a+1     # 有引用,引用外部函数变量
        print(f'a的值为{a}')
    # 4.返回内置函数
    return func_inner       # 有返回,返回内部函数名

# 调用func_outer函数
my_fn = func_outer()  # 等价于: my_fn = func_inner
my_fn()  # 101
my_fn()  # 102
my_fn()  # 103

装饰器

作用:

        装饰器的作用是不改变原有函数的基础上,给原有函数增加额外功能。 装饰器本质上就是一个闭包函数。

构成条件:

        ①有嵌套:在函数嵌套(函数里面再定义函数)的前提下;

        ②有引用:内部函数使用了外部函数的变量(还包括外部函数的参数);

        ③有返回:外部函数返回了内部函数名;

        ④有额外功能:给需要装饰的原有函数增加额外功能。

四种场景写法:

"""
装饰器细节:
    1. 装饰器的目的是: 在不改变原有函数的基上, 给原函数增加 额外功能
    2. 装饰器常用与法主要是: 语法糖形式, 即: @装饰器名
    3, 使用装饰器的小技巧: 保证装饰器的 内置函数格式 和 原函数(要被装饰的函数) 格式保持一致,都是无参无返回,无参有返回...
"""
# 场景一:无参无返回
# 1.定义装饰器
def print_info(fn_name):     # fn_name: 表示要被装饰的函数名
    def fn_inner():          # 内置函数, 格式要和 原函数(被装饰的函数) 保持一致
        print('正在努力计算中...')
        fn_name()
    return fn_inner

# 2.定义原函数,(即: 要被装饰的函数)
@print_info       # 这个是语法糖写法, 等价于: get_sum = print_info(get_sum)
def get_sum():
    a = 10
    b = 20
    sum = a + b
    print(f'求和结果为{sum}')

# 3.调用函数
# get_sum = print_info(get_sum)     # 原始写法, 看懂即可, 一般不用.
get_sum()

# 场景二:无参有返回
# 1.定义装饰器
def print_info(fn_name):     # fn_name: 表示要被装饰的函数名
    def fn_inner():          # 内置函数, 格式要和 原函数(被装饰的函数) 保持一致
        print('正在努力计算中...')
        return fn_name()
    return fn_inner

# 2.定义原函数,(即: 要被装饰的函数)
@print_info       # 这个是语法糖写法, 等价于: get_sum = print_info(get_sum)
def get_sum():
    a = 10
    b = 20
    sum = a + b
    print(f'求和结果为{sum}')
    return sum

# 3.调用函数
# get_sum = print_info(get_sum)     # 原始写法, 看懂即可, 一般不用.
get_sum()

# 场景三:有参无返回
# 1.定义装饰器
def print_info(fn_name):     # fn_name: 表示要被装饰的函数名
    def fn_inner(a,b):          # 内置函数, 格式要和 原函数(被装饰的函数) 保持一致
        print('正在努力计算中...')
        fn_name(a,b)
    return fn_inner

# 2.定义原函数,(即: 要被装饰的函数)
@print_info       # 这个是语法糖写法, 等价于: get_sum = print_info(get_sum)
def get_sum(a,b):
    sum = a + b
    print(f'求和结果为{sum}')

# 3.调用函数
# get_sum = print_info(get_sum)     # 原始写法, 看懂即可, 一般不用.
get_sum(100,200)

# 场景四:有参有返回
# 1.定义装饰器
def print_info(fn_name):     # fn_name: 表示要被装饰的函数名
    def fn_inner():          # 内置函数, 格式要和 原函数(被装饰的函数) 保持一致
        print('正在努力计算中...')
        return fn_name()
    return fn_inner

# 2.定义原函数,(即: 要被装饰的函数)
@print_info       # 这个是语法糖写法, 等价于: get_sum = print_info(get_sum)
def get_sum():
    a = 10
    b = 20
    sum = a + b
    print(f'求和结果为{sum}')
    return sum

# 3.调用函数
# get_sum = print_info(get_sum)     # 原始写法, 看懂即可, 一般不用.
get_sum()

# 场景四:有参有返回
# 1.定义装饰器
def print_info(fn_name):     # fn_name: 表示要被装饰的函数名
    def fn_inner(a,b):          # 内置函数, 格式要和 原函数(被装饰的函数) 保持一致
        print('正在努力计算中...')
        return fn_name(a,b)
    return fn_inner

# 2.定义原函数,(即: 要被装饰的函数)
@print_info       # 这个是语法糖写法, 等价于: get_sum = print_info(get_sum)
def get_sum(a,b):
    sum = a + b
    print(f'求和结果为{sum}')
    return sum

# 3.调用函数
# get_sum = print_info(get_sum)     # 原始写法, 看懂即可, 一般不用.
get_sum(33,66)

带参数的装饰器:

"""
案例:
    演示不带参数的装饰器.
目的:
    演示1个装饰器 可以用来 装饰 多个函数
需求:
    定义一个既能装饰减法运算, 又能装饰加法运算的装饰器, 即: 带有参数的装饰器
"""
# 1.定义装饰器
def logging(flag):                              # 有嵌套,接收:装饰器的参数 + -
    def decorator(fn_name):                     # 有嵌套 接收原函数名
        def inner(num1,num2):                   # 有嵌套 给函数增加额外功能
            if flag =='+':
                print('正在努力计算 加法 中...')
            if flag =='-':
                print('正在努力计算 减法 中...')
            return fn_name(num1,num2)
        return inner
    return decorator


# 2.定义函数,加法运算
@logging('+')
def get_sum(a,b):
    sum = a+b
    return sum

# 3.定义函数,减法运算
@logging('-')
def get_sub(a,b):
    sub = a-b
    return sub

# 4.调用函数
sum = get_sum(10,7)
print(f'相加为{sum}')

sub = get_sub(10,7)
print(f'相减为{sub}')

  • 18
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值