【python】闭包和装饰器

前置知识:

  1. 函数的本质就是变量名
  2. 可以把函数作为参数传递,例如:
def func():
    print("我是func")
    
# 接收的fn是个函数
def handle(fn):
# 调用函数
    fn()

handle(func)
  1. 可以把函数作为返回值返回,例如
def func():

    def func2():
        print("我是func2")
    # func2函数作为返回值
    return func2

fn = func()
fn()

闭包

闭包:内层函数对外层函数的变量的使用
作用1:让一个变量被外部访问,但是不能修改
作用2:让一个变量常驻内存

def func():
    a = 10
    def inner():
        print(a)
        return a
    return inner

# 函数外部访问到了变量a
fn = func()
fn()

装饰器

本质: 装饰器的本质就是一个函数,该函数的参数是被装饰的函数,返回值是装饰后的函数
作用: 装饰器可以在不改变原有代码的基础上,给函数添加新的功能

一、装饰器雏形(理解)

装饰器雏形

def wrapper(fn):
    def inner():
        print("执行被装饰函数之前")
        fn()
        print("执行被装饰函数之后")
    return inner

def add():
    print("我是add")
    
# 向wrapper函数传入了add函数,返回的函数命名为add
add = wrapper(add) # 装饰器的关键语句!!!
add() # 这里执行add()相当于执行inner(),因为wrapper返回的是inner函数

装饰器雏形用语法糖的形式写

def wrapper(fn):
    def inner():
        print("执行被装饰函数之前")
        fn()
        print("执行被装饰函数之后")
    return inner

@wrapper    # 用语法糖/装饰器的写法应该这么写,等价于执行add = wrapper(add)
def add():
    print("我是add")
    
add() # 这里执行add()相当于执行inner(),因为wrapper返回的是inner函数

二 、通用装饰器(重点记住)

通用装饰器的固定写法如下:
(wrapper、inner、fn都是可以随意命名的,并非固定的)

def wrapper(fn):
    # *args和**kwargs用于接受被装饰函数的参数
    def inner(*args, **kwargs):
        """在被装饰函数之前执行的操作"""
        # 注意:这里的*和**是将args和**kwargs打散传递给fn函数
        ret = fn(*args, **kwargs) # 被装饰函数
        """在被装饰函数之后执行的操作"""
        return ret   # 处理被装饰函数的返回值
    return inner

三、高阶装饰器(理解)

即同一个函数被多个装饰器装饰,按照就近原则解读。
举例:

def wrapper1(fn):
    def inner(*args, **kwargs):
        print("wrapper1-before")
        ret = fn(*args, **kwargs)
        print("wrapper1-after")
        return ret

    return inner


def wrapper2(fn):
    def inner(*args, **kwargs):
        print("wrapper2-before")
        ret = fn(*args, **kwargs)
        print("wrapper2-after")
        return ret

    return inner
    
@wrapper2
@wrapper1
def target():
    print("我是target")

"""
先被wrapper1装饰,再被wrapper2装饰
因此target()函数运行的打印结果为:
wrapper2-before
wrapper1-before
我是target
wrapper1-after
wrapper2-after
"""
target()

四、带参数的装饰器(理解)

在通用装饰器的外面再套一层函数,传入需要的参数,然后返回这个装饰器。
举例:

def wrapper_outer(name):
    def wrapper(fn):
        def inner(*args, **kwargs):
            print(f"wrapper-before-{name}")
            ret = fn(*args, **kwargs)
            print(f"wrapper-after-{name}")
            return ret
        return inner
    return wrapper

# wrapper_outer("啦啦啦")相当于运行了这个函数,返回了一个装饰器
# 在装饰器前面再加个@来使用装饰器,装饰对应的函数
@wrapper_outer("啦啦啦")
def target1():
    print("我是target1")

@wrapper_outer("哦哦哦")
def target2():
    print("我是target2")

target1()
target2()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值