1. 程式人生 > 其它 >python的閉包與裝飾器

python的閉包與裝飾器

閉包指內部函式對外部函式作用域裡變數的引用

內部函式與外部函式:

def func():#外部函式
    print("this is func")
    def func1(num):#內部函式
        print("this is func1")

由於內部函式的宣告是在外部函式的作用域內,所以我們在外面是無法呼叫內部函式的,如何呼叫?在func()中return func1

def func():#外部函式
    a=1
    print("this is func")
    def func1():
        print("this is func1")
    
return func1 var=func() var()

函式的閉包:

def func():#外部函式
    a=1
    print("this is func")
    def func1(num):
        print("this is func1")
        print(num+a)
    return func1

var=func()
var(3)

讓內部函式可以使用外部函式的變數,也就是說呼叫func()時除了func1() return出來了,外部函式中用到的變數也存活下來了

閉包內的閉包函式(func1())私有化了變數,完成了資料的封裝,類似於面向物件

mylist=[1,2,3,4,5]

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

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

del var才宣佈閉包生命週期的結束,由於閉包包裝了一些資料,所以當大規模使用的時候是對記憶體不利的

實現裝飾器的時候會利用到閉包,裝飾器,語法糖@

裝飾器:

@func1
def func():
    print("aaa")

在我們執行func()時,會首先執行func1()中的內容

如果我們去掉裝飾器@func1,那麼func就只會執行print,加上裝飾器的話就會新增某些功能。因此裝飾器的意義就是不影響原有函式的功能,新增新的功能

一般用於拿到了別人的第三方api,覺得功能簡陋還需要新增功能時,就可以使用裝飾器

def func1(func):
    def func2():
        print("112233")
        return func()
    return func2

@func1
def myPrint():
    print("hello, this is my print")
    
myPrint()

相當於給myPrint函式做了裝飾,我們呼叫的myPrint()=func2()+func(),這裡的func是傳進來的引數,也就是myPrint本身

相當於func1(myPrint)()

整個呼叫流程:

func1將被修飾函式myPrint作為引數接收上來

func1接收到了myPrint後返回內部的func2

func2返回回來之後,將返回回來的結果繼續加上括號

https://www.cnblogs.com/wangtianning1223/p/14118933.html中的程式其實相當於

funA(funB(funC))()

因此funA,funB的執行順序是相反的,而warp的順序是正序

帶引數的裝飾器,多一層包裝接收裝飾器引數

def arg_func(sex):
    def func1(a):
        def func():
            if sex=="man":
                print("you are man")
            if sex=="woman":
                print("you are woman")
            return a()
        return func
    return func1

@arg_func(sex="man")
def man():
    print("work for money")

@arg_func(sex="woman")
def woman():
    print("work for money")
    
man()
woman()

相當於arg_func(sex)(func)()==>func1()==>func2()==>print("you are man")+man() || print("you are woman")+woman()

被裝飾的函式帶引數,只需在最內部函式傳入引數即可

def func1(func):
    def func2(x,y):
        print(x,y)
        x+=5
        y+=5
        return func(x,y)
    return func2

@func1
def mysum(a,b):#a=a+5,b=b+5使用裝飾器修改
    print(a+b)
    
mysum(1,2)

注意return func()的時候要把引數xy也返回

無情的摸魚機器