這個概念真的有點難,我思考了兩天才開始寫這篇教程豫领,這和java 真的有點不太一樣氧卧,沒事,咱一步一步來氏堤,一點點分解沙绝。
以下內(nèi)容僅作者理解,并不權威鼠锈,如果有不恰當?shù)牡胤缴撩剩埣夹g大牛指點。
在python中 函數(shù)屬于‘一等公民’购笆,可以相互嵌套粗悯。
看一個例子:
這個例子很淺顯易懂同欠,只是函數(shù)進行了嵌套
接下來看一個稍微復雜一點的例子
這里就存在一個閉包的概念样傍,我們先看一下:
閉包:在一個外函數(shù)中定義了一個內(nèi)函數(shù),內(nèi)函數(shù)里運用了外函數(shù)的臨時變量铺遂,并且外函數(shù)的返回值是內(nèi)函數(shù)的引用衫哥。這樣就構成了一個閉包。
#在一個外函數(shù)(outer)中定義了一個內(nèi)函數(shù)(inner)襟锐,內(nèi)函數(shù)里運用了外函數(shù)的臨時變量(x,y=10)撤逢,并且外函數(shù)的返回值是內(nèi)函數(shù)的引用(return inner())。這樣就構成了一個閉包。
這里特殊說明一下蚊荣,按照我們通常的經(jīng)驗初狰,一個函數(shù)被調(diào)用的時候,會在內(nèi)存空間分配一部分空間互例,來存儲在和函數(shù)內(nèi)部的變量等奢入,當這個函數(shù)調(diào)用完成之后,這一部分空間會被釋放媳叨。但是閉包有一點點不同俊马,當外層函數(shù)執(zhí)行完后,內(nèi)層函數(shù)沒有肩杈,它的引用依然被持有柴我,所以外層函數(shù)的局部變量不能被釋放,這個局部變量就被綁定在內(nèi)層函數(shù)上了扩然,然后外層函數(shù)再被釋放艘儒。
這里有一個錯誤 return inner 不能加()差別小伙伴們自己想清楚哦
20190531補充
這個東西還是要講一下,不然講下一個話題夫偶,不太好開展
關于inner() 和inner
inner 其實通俗的理解他就是一個函數(shù)的名字界睁,這個名字指向一個函數(shù),當后面沒有小括號的時候兵拢,它可以被傳遞翻斟,被賦值,但是不會去執(zhí)行说铃。
inner()加上()访惜,就是告訴程序,通過inner 名字找到這個函數(shù)腻扇,然后執(zhí)行這個函數(shù)
通俗的講债热,如何能形成閉包?
1.存在函數(shù)的嵌套2.內(nèi)層函數(shù)要引用外層函數(shù)的變量3外層函數(shù)要返回內(nèi)層函數(shù)的引用
為什么要使用閉包幼苛?
舉個例子窒篱,這個例子是從別人那里偷來的
定義直線 y = a*x+b? 如何使用閉包 創(chuàng)建一個函數(shù)可以生成對于任意a,b的直線呢舶沿?
在上述代碼中,內(nèi)部函數(shù)line() 中其實沒有臨時參數(shù)a,b.在python 中如果在自己的作用于里沒有找到相應的參數(shù)括荡,即像上一級控件中去尋找高镐,在外部函數(shù)line_fun 中找到使用
如果我們想處理 過坐標(0,1)這一點的所有直線 顯然是y = a*x +1 這樣一條直線,如果想像剛才一樣來一個方法 大家感受一下
之所以沒有改變b,就是剛才所說的作用域的問題一汽,內(nèi)部函數(shù)在內(nèi)部沒有找到參數(shù)b,去外層函數(shù)尋找 尋找后使用外層函數(shù)的b = 1避消;可以打印一下兩個b的地址發(fā)現(xiàn)兩個b 根本不是同一個b
為什么?(這也是為什么叫閉包)
閉包作為對象被返回時召夹,它的引用變量就已經(jīng)確定(已經(jīng)保存在它的__closure__屬性中)岩喷,不會再被修改。是的监憎,閉包在被返回時纱意,它的所有變量就已經(jīng)固定,形成了一個封閉的對象鲸阔,這個對象包含了其引用的所有外部偷霉、內(nèi)部變量和表達式。閉包的參數(shù)例外褐筛。
print(line_fun(10).__closure__)
# (< cell at 0x10a07cb58: int object at 0x109e366c0 >, < cell at 0x10a07cb88: int object at 0x109e365a0 >)
# __closure__屬性返回的是一個元組對象类少,包含了閉包引用的外部變量。
閉包的實際應用渔扎?
暫時還木有用到 用到后過來添加