【python】閉包

閉包

所謂閉包,就是將組成函數(shù)的語句和這些語句的執(zhí)行環(huán)境打包在一起時(shí),得到的對(duì)象。

  • 栗子1
def count():
    fs = []
    for i in range(1, 4):
        def f():
             return i*i
        fs.append(f) #這里的 f 已經(jīng)是一個(gè)函數(shù) 加入了
    return fs
f1, f2, f3 = count()
>>> f1()
9
>>> f2()
9
>>> f3()
9

上面這個(gè)函數(shù)有點(diǎn)糾結(jié)!
糾結(jié)點(diǎn)1:f1, f2, f3 = count()是什么意思?
:f1, f2, f3 = count() 這個(gè)并不是我猜想3個(gè)都平等同樣的指向fs這個(gè)list,更有可能的是,這個(gè)三個(gè)這是分別指向了list中的3個(gè)元素
(1)只有元素才有可能是int
(2)如果只寫成f1,f2 = count()的話
會(huì)報(bào)錯(cuò)ValueError: too many values to unpack (expected 2)
寫成f1,f2,f3,f4= count()的話
會(huì)報(bào)錯(cuò)ValueError: need more than 3 values to unpack
(3)打印出來看

>>>print(f1,f2,f3)
返回3個(gè)<function count.<locals>.f at 0x00000000037F5400>
>>>f1= count
>>>print(f1())
[<function count.<locals>.f at 0x0000000002F65268>,
<function count.<locals>.f at 0x0000000002F65400>,
<function count.<locals>.f at 0x0000000002F65488>]

說明,如果返回一個(gè)列表,那么這個(gè)列表每個(gè)元素都是函數(shù)。
糾結(jié)點(diǎn)2:為什么f1(),f2(),f3()都返回9,即為啥列表中的元素都是9?
原因是返回函數(shù)引用了變量i,下面來解析下f1,f2,f3=count()這句的執(zhí)行過程:
  當(dāng)i=1, 執(zhí)行for循環(huán), 結(jié)果返回函數(shù)f的函數(shù)地址,存在列表fs中的第一個(gè)位置上。
   當(dāng)i=2, 由于fs列表中第一個(gè)元素所指的函數(shù)中的i是count函數(shù)的局部變量,i也指向了2;然后執(zhí)行for循環(huán), 結(jié)果返回函數(shù)f的函數(shù)地址,存在列表fs中的第二個(gè)位置上。
  當(dāng)i=3, 同理,在fs列表第一個(gè)和第二個(gè)元素所指的函數(shù)中的i變量指向了3; 然后執(zhí)行for循環(huán), 結(jié)果返回函數(shù)f的函數(shù)地址,存在列表fs中的第三個(gè)位置上。
  所以在調(diào)用f1()的時(shí)候,函數(shù)中的i是指向3的:
f1():
  return 3*3
同理f2(), f3()結(jié)果都為9

注意:返回閉包時(shí)牢記的一點(diǎn)就是:返回函數(shù)不要引用任何循環(huán)變量,或者后續(xù)會(huì)發(fā)生變化的變量。
  • 栗子2:如果一定要引用循環(huán)變量怎么辦?方法是再創(chuàng)建一個(gè)函數(shù),用該函數(shù)的參數(shù)綁定循環(huán)變量當(dāng)前的值,無論該循環(huán)變量后續(xù)如何更改,已綁定到函數(shù)參數(shù)的值不變:
def count():
    def f(j):
        def g():
            return j*j
        return g
    fs = []
    for i in range(1, 4):
        fs.append(f(i)) # f(i)立刻被執(zhí)行,因此i的當(dāng)前值被傳入f()
    return fs

注意:當(dāng)i=1時(shí),f(1)即讓j指向1,f(1)立即被執(zhí)行,返回值是g函數(shù),g函數(shù)作為參數(shù)傳入fs.append()里
當(dāng)i=2時(shí),f(2)即讓j指向2,此時(shí)j不是count的局部變量,不會(huì)影響到i=1是f(1)中j的指向。即函數(shù)f的參數(shù)綁定循環(huán)變量當(dāng)前的值, 而不是循環(huán)變量本身。

>>> f1, f2, f3 = count()
>>> f1()
1
>>> f2()
4
>>> f3()
9
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • //Clojure入門教程: Clojure – Functional Programming for the J...
    葡萄喃喃囈語閱讀 4,021評(píng)論 0 7
  • 什么是閉包? 簡(jiǎn)單說,閉包就是根據(jù)不同的配置信息得到不同的結(jié)果 再來看看專業(yè)的解釋:閉包(Closure)是詞法閉...
    chen_000閱讀 175評(píng)論 0 0
  • 運(yùn)行結(jié)果如下: 閉包的定義:在函數(shù)內(nèi)部再定義一個(gè)函數(shù),并且這個(gè)函數(shù)用到了外邊函數(shù)的變量,那么將這個(gè)函數(shù)以及用到的一...
    魔法高校的劣等生閱讀 558評(píng)論 0 0
  • 作用域 在理解閉包前,先看一個(gè)函數(shù): 可以看到func()函數(shù)內(nèi)部的變量無法在函數(shù)外部使用 全局變量out_fun...
    XYZeroing閱讀 1,032評(píng)論 0 10
  • 沁園春 賀北京絲綢之路峰會(huì)論壇 中華新韻八寒 詞/老財(cái)神 五月京都,日麗風(fēng)和...
    老財(cái)神閱讀 250評(píng)論 0 2

友情鏈接更多精彩內(nèi)容