python 闭包 装饰器

python 闭包 装饰器,第1张

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

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/568837.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-09
下一篇 2022-04-09

发表评论

登录后才能评论

评论列表(0条)

保存