python 闭包 装饰器

1 闭包:保小

闭包

函数内的属性,都是有生命周期的,都是在函数执行期间,函数执行完,就会被回收。但可以通过闭包,将函数内的属性给保留下来,除非通过 del 删除掉,否则就是存在的。

内部函数对外部函数作用域(肚子里的东西)里变量的引用

def func():  # 外部函数
    print("this is function")

    def func1():  # 内部函数
        print("this is function1")
func()
#输出
# this is function

若我想用func1,该怎么办呢?将func1()返回就可以用了啊

def func():  # 外部函数
    print("this is function")

    def func1():  # 内部函数
        print("this is function1")
    return func1


var = func()  # 这时候return回来func1
var()   # var == func1,var()==func1()
#输出
#this is function
#this is function1
# 一个真正意义上闭包的例子:函数层面的
# 内部函数对外部函数作用域里 *变量* 的引用(仔细理解)

def func():  # 外部函数
    a = 1  # 外部函数作用域里的变量
    print("this is function")

    def func1(num):  # 内部函数
        print("this is function1")
        print(num + a)   # 将外部a的保下来。通过return func1函数保下来
        # (内部函数对外部函数作用域里 *变量* 的引用)

    return func1  # 返回func1的函数名


var = func()  # 这时候return回来func1
var(3)   # var == func1,var()==func1()
# 输出
# this is function
# this is function1
# 4

但是此时a是在var里面的,若def val,那么此时a才会被真正意义的删除。(看下面的例子),我们会发现obj其实是没有被删除的,obj[0] 仍然在叠加的状态。

mylist = [1, 2, 3, 4]


def func(obj):
    print('func', obj)

    def func1():
        obj[0] += 1
        print("func1", obj)

    return func1


var = func(mylist)
var()
var()
var()

# 输出
#func [1, 2, 3, 4]
#func1 [2, 2, 3, 4]
#func1 [3, 2, 3, 4]
#func1 [4, 2, 3, 4]

闭包的意义:闭包是func(),闭包函数func1()
闭包内的闭包函数func1私有化了变量,完成了数据的封装,类似于面向对象。

2 装饰器(也叫语法糖 @)

装饰器存在的意义:不影响原有函数的功能,而且还可以添加新的功能。
场景:对不可修改的第三方API进行添加新功能。

2.1 装饰器

# 装饰器 基于闭包
def func1(func):  # 闭包函数的参数是外部闭包函数的参数,func是被装饰的函数对象, func是形参函数!
    def func2():
        print("aaaabbbb")
        return func()  # 返回了外部函数接收的参数被装饰函数的调用

    return func2


# return func  返回了函数名
# return func()  返回的是一个函数调用
@func1  # 相当于 myprint = func1(myprint),这就是装饰器的功能
def myprint():
    print("你好,我是print")


myprint()  # 由于被装饰了,所以此处执行的实际为func1(myprint)(),接收被装饰的函数作为参数,而且还要被继续调用一次

# 流程:
# @func1相当于myprint == func1(myprint) 得到func2,即myprint=func2
# 而myprint() = func2(),所以执行func2(), 然后得到print("aaaabbbb"),然后得到func(),
# 而func=myprint,所以func()=myprint(),打印出print("你好,我是print")

# myprint()==func2()+func()
# 而func==myprint,所以
# myprint()==func2()+myprint()

2.2 装饰器函数带参数:多一层包装来接收装饰器的参数

# 要求:
# 调用men()时候,print("好好上班。你不可以生娃")
# 调用women()时候,print("好好上班。你可以生娃")
# def men():
#     print("好好上班。")

# def women():
#     print("好好上班。")


def func1(func,sex):
    def func2():
        if sex == "men":
            print("你不可以生娃")
        if sex == "women":
            print("你可以生娃")
        return func()

    return func2


@func1(sex='men')
def men():
    print("好好上班。")


@func1(sex='women')  # 但是这样会报错,所以其实还需要一个外层函数
def women():
    print("好好上班。")


men()  # func1(men)()

# 报错
@func1(sex='men')
TypeError: func1() missing 1 required positional argument: 'func'

但是这样会报错,所以其实还需要一个外层函数,如下:


def func0(sex):
    def func1(func):
        def func2():
            if sex == "men":
                print("你不可以生娃")
            if sex == "women":
                print("你可以生娃")
            return func()

        return func2
    return func1

# 带参装饰器:func0(sex='men')()()
#1、func0(sex='men')——>func1
#2、func1()——>func2  # 用了第一个()
#3、func2()用第二个()——>func()==men()

@func0(sex='men')
def men():
    print("好好上班。")


@func0(sex='women')  
def women():
    print("好好上班。")


men()  # men()相当于func0(sex='men')()()
women()

# 输出
你不可以生娃
好好上班。
你可以生娃
好好上班。

2.3 被装饰的函数带参数:只需要在最内部函数传入

# 求和:接收两个参数。
# 实现被装饰函数,接收两个参数,并return a+b的值,并希望a,b本身都+5,不允许在mysum中实现。

def func1(func):
    def func2(x, y):
        print(x, y)
        x += 5
        y += 5
        # x = 'a'
        # y = 'b'
        # 最后会实现:1+2 = ab
        return func(x, y)

    return func2


@func1
def mysum(a, b):
    print(a + b)


mysum(1, 2)
# 即得到 1+2 =13
# 1 2
# 13

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值