<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Python入門(mén)系列27 - 進(jìn)階必修之閉包(二)

          共 4445字,需瀏覽 9分鐘

           ·

          2019-11-16 23:21

          Python入門(mén)系列27

          5c8f7182fccbf36bdde51189b732394a.webp

          進(jìn)階必修之閉包(二)


          本篇閱讀時(shí)間約為7分鐘。


          1

          前言


          忘記之前的閉包(一),可以點(diǎn)擊下面的鏈接進(jìn)行回顧。


          Python入門(mén)系列26 - 進(jìn)階必修之閉包(一)


          這里還是多說(shuō)一句,閉包在編寫(xiě)代碼的過(guò)程中并不是必不可少的,某些場(chǎng)景下使用閉包,對(duì)編程的代碼在架構(gòu)上會(huì)起到精簡(jiǎn)代碼的作用,但是絕不是說(shuō)少了閉包就無(wú)法實(shí)現(xiàn)功能了!就像類和對(duì)象一樣,沒(méi)有對(duì)象和類就不能寫(xiě)代碼了嗎??我們依然可以用普通的函數(shù)去實(shí)現(xiàn)某些功能!


          2

          舉個(gè)栗子看閉包


          c8bff9542df00655b102b37d09c21769.webp


          西游記的故事大家都有所聽(tīng)說(shuō),唐玄奘西天一去,取經(jīng)之路長(zhǎng)達(dá)十萬(wàn)八千里,而悟空一跟頭就能翻到地方,卻依然一路護(hù)送唐僧,其實(shí)這是有原由的:如來(lái)佛祖在取經(jīng)任務(wù)前就跟這取經(jīng)小團(tuán)隊(duì)說(shuō)了,你們要想取到這真經(jīng),就得踏踏實(shí)實(shí),一步一腳印,還要過(guò)這九九八十一難。而中途經(jīng)過(guò)了:


          長(zhǎng)安(今陜西西安)——秦州(今甘肅天水)——蘭州——涼州(今甘肅武威)——瓜州(今甘肅安西縣東南)——玉門(mén)關(guān)——伊吾(今新疆哈密)——高昌(今新疆吐魯番)——阿耆尼國(guó)(今新疆焉耆)——屈支國(guó)(今新疆庫(kù)車(chē))——跋逯迦國(guó)(今新疆阿克蘇)——凌山(今天山穆蘇爾嶺)——大清池(今吉爾吉斯斯坦伊塞克湖)——素葉城(即碎葉城,今吉爾吉斯斯坦托克馬克西南)——昭武九姓七國(guó)(都在今烏茲別克斯坦境內(nèi))——鐵門(mén)(烏茲別克斯坦南部茲嘎拉山口)——今阿富汗北境——大雪山(今興都庫(kù)什山)——今阿富汗貝格拉姆——巴基斯坦白沙瓦城——印度


          這么一寫(xiě)出來(lái),唐僧走了這么遠(yuǎn)的嗎!23333333333309a02b5993fa3ab1ab0c10e2d0b49adf.webp....回歸正題,唐僧師父是從東土大唐而來(lái),東土大唐的長(zhǎng)安作為整個(gè)西游的起點(diǎn),其中每過(guò)之地的總行進(jìn)距離應(yīng)該是在上一個(gè)地點(diǎn)的距離進(jìn)行累加。比如在長(zhǎng)安時(shí),起始的西游距離是0,當(dāng)經(jīng)歷過(guò)一難之后,走到了秦州,行進(jìn)距離增加到100里,再過(guò)一劫,到了蘭州,秦州到蘭州的距離是200里,此時(shí)行進(jìn)距離是在100里的基礎(chǔ)上加200里,到蘭州時(shí),總行進(jìn)了300里,后續(xù)以此類推....每到一個(gè)國(guó)度,使用中途經(jīng)過(guò)的距離與上次進(jìn)行累加,請(qǐng)打印輸出每次途徑國(guó)度的總行進(jìn)距離(各國(guó)度到長(zhǎng)安的距離)。


          接下來(lái),請(qǐng)你用程序來(lái)實(shí)現(xiàn)一下。


          3

          非閉包實(shí)現(xiàn)栗子


          首先來(lái)看下,非閉包實(shí)現(xiàn)的例子,在開(kāi)題之時(shí)就說(shuō)過(guò),閉包并不是必不可少的東西,即使沒(méi)有閉包,功能依然可以實(shí)現(xiàn)。依然是有邏輯的講下最終代碼的實(shí)現(xiàn),步驟如下:


          1. 定義walk函數(shù),將每次的間隔距離傳入到其中,每次進(jìn)行相加看結(jié)果


          ChangAn_distance?=?0

          def?walk(midway_distance):
          ????total_distance?=?ChangAn_distance?+?midway_distance
          ????return?total_distance

          print(f'從長(zhǎng)安到秦州的總距離{walk(100)}')
          print(f'從長(zhǎng)安到蘭州的總距離:{walk(200)}')
          print(f'從長(zhǎng)安到?jīng)鲋莸目偩嚯x{walk(300)}')


          講解:定義初始變量 - 長(zhǎng)安街的距離,再定義一個(gè)walk走路的函數(shù),將每次中途的距離傳入此函數(shù)中,在其中計(jì)算每次相加的距離,將結(jié)果返回,如下:


          0299deded51a422a52380b526364caa4.webp


          這樣寫(xiě)的最終結(jié)果,只是打印出了每次中間的距離,比如100,就是長(zhǎng)安到泰州的距離,200里是泰州到蘭州的距離,而不應(yīng)該是長(zhǎng)安到蘭州的總距離。所以這樣寫(xiě)是不對(duì)的,繼續(xù)看步驟2。


          2. 將計(jì)算的總距離賦值給初始值ChangAn_distance


          ChangAn_distance?=?0

          def?walk(midway_distance):
          ????total_distance?=?ChangAn_distance?+?midway_distance
          ????ChangAn_distance?=?total_distance
          ????return?ChangAn_distance

          print(f'從長(zhǎng)安到秦州的總距離{walk(100)}')
          print(f'從長(zhǎng)安到蘭州的總距離:{walk(200)}')
          print(f'從長(zhǎng)安到?jīng)鲋莸目偩嚯x{walk(300)}')


          講解:將計(jì)算的總距離賦值給初始距離,這樣一來(lái)每次 ChangAn_distance 就會(huì)進(jìn)行累加,最終將其返回就是總距離了。看第一個(gè)print執(zhí)行時(shí),調(diào)用了walk函數(shù)傳入100,total_distance 算出來(lái)得100,ChangAn_distance 接下來(lái)被賦值為100,其自身從0變?yōu)榱?00;到第二個(gè)print時(shí),此時(shí)的?ChangAn_distance 已經(jīng)變?yōu)榱?00,所以在第二個(gè)print時(shí)候調(diào)用的walk函數(shù),里面的 total_distance 算出來(lái)得就是 100 + 200 = 300,以此類推.....


          乍一看這段思維邏輯是沒(méi)有任何問(wèn)題的,但是若是執(zhí)行時(shí),就會(huì)像下圖一樣報(bào)錯(cuò):


          4341d66972b81f2379a960e0aa84fba0.webp


          錯(cuò)誤信息是:本地變量 ChangAn_distance?在引用之前沒(méi)有被定義。有人可能會(huì)想到上節(jié)中說(shuō)到的,函數(shù)內(nèi)部找不到變量,會(huì)向外層尋找,外層不是已經(jīng)初始化了嗎?怎么還會(huì)報(bào)錯(cuò)呢!實(shí)際上是因?yàn)榇诵写a受到了賦值變量的影響,也就是16行寫(xiě)到的代碼,可以看步驟1中,若將16行代碼抹掉,是不會(huì)報(bào)錯(cuò)的。在Python中,16行代碼的左側(cè)變量?ChangAn_distance ,解釋器一旦發(fā)現(xiàn)它在左側(cè),說(shuō)明在局部的函數(shù)中就認(rèn)為是對(duì)其進(jìn)行初始化了,但是在walk函數(shù)中并沒(méi)有對(duì)其進(jìn)行初始化,所以報(bào)錯(cuò)了。


          3. 將 ChangAn_distance 設(shè)為全局變量即可


          ChangAn_distance?=?0

          def?walk(midway_distance):
          ????global?ChangAn_distance
          ????total_distance?=?ChangAn_distance?+?midway_distance
          ????ChangAn_distance?=?total_distance
          ????return?ChangAn_distance

          print(f'從長(zhǎng)安到秦州的總距離{walk(100)}')
          print(f'從長(zhǎng)安到蘭州的總距離:{walk(200)}')
          print(f'從長(zhǎng)安到?jīng)鲋莸目偩嚯x{walk(300)}')


          通過(guò)global關(guān)鍵詞,可以將變量定義為全局的變量,此時(shí)在進(jìn)行調(diào)用就不會(huì)出現(xiàn)步驟2中的錯(cuò)誤了,如下:


          ed50f65751c8eb23373be5a57ef6d7f3.webp


          個(gè)答案正是程序的正確答案!唐僧感到欣慰啊........09a02b5993fa3ab1ab0c10e2d0b49adf.webp


          4

          閉包實(shí)現(xiàn)栗子


          前面又鋪墊了這么多,現(xiàn)在讓我們來(lái)用閉包實(shí)現(xiàn)一下唐僧取經(jīng)的例子!依然是分為幾個(gè)步驟,如下:


          1. 定義閉包函數(shù),外層函數(shù)假設(shè)是騎馬,內(nèi)層函數(shù)是走路


          西天取經(jīng)之路,大部分時(shí)間唐僧是騎馬行進(jìn)的,這樣一來(lái),馬可以作為一個(gè)代步工具來(lái)使用,當(dāng)沒(méi)有馬的時(shí)候,只好自己走路咯。所以定義外層函數(shù)為騎馬,內(nèi)層函數(shù)為走路:


          ChangAn_distance?=?0

          def?ride_horse(init_distance):
          ????def?walk(midway_distance):
          ????????total_distance?=?init_distance?+?midway_distance
          ????????init_distance?=?total_distance
          ????????return?init_distance

          ????return?walk

          w?=?ride_horse(ChangAn_distance)
          print(f'從長(zhǎng)安到秦州的總距離{w(100)}')
          print(f'從長(zhǎng)安到蘭州的總距離:{w(200)}')
          print(f'從長(zhǎng)安到?jīng)鲋莸目偩嚯x{w(300)}')


          通過(guò)白龍馬這層代步工具,我們可以在起始的時(shí)候,將起始距離(ChangAn_distance)傳入到騎馬函數(shù)(ride_horse)里,使用閉包的特性,在調(diào)用外層函數(shù)時(shí),將內(nèi)層的walk函數(shù)返回從而得到w,調(diào)用w將中途距離(100,200,300)傳入,最后輸出打印!walk函數(shù)中的計(jì)算邏輯是和非閉包一樣的,看懂了非閉包后,看這個(gè)也是一樣的,于是運(yùn)行如下:


          6ee15e4d36be3602bf5ec1d5f0038e53.webp


          2. 使用 nonlocal 關(guān)鍵詞告知python變量非本地變量


          47598d9d8104ef1a8017e99e3c8aa627.webp


          只需使用 nonlocal 定義變量,方可告知Python此變量并不是本地變量即可。


          有人可能會(huì)有疑問(wèn),這寫(xiě)法是閉包嗎?結(jié)合上節(jié)課說(shuō)到的,不是要有個(gè)環(huán)境變量與內(nèi)部函數(shù)組成封閉在一起使用嗎!想到這里的同學(xué),說(shuō)明動(dòng)腦思考了喲!沒(méi)錯(cuò),在這個(gè)例子中,作為環(huán)境變量而言的其實(shí)是外部函數(shù)(ride_horse)中的形參,也就是init_distance!來(lái)驗(yàn)證下唄:


          ChangAn_distance?=?0

          def?ride_horse(init_distance):
          ????def?walk(midway_distance):
          ????????nonlocal?init_distance
          ????????total_distance?=?init_distance?+?midway_distance
          ????????init_distance?=?total_distance
          ????????return?init_distance

          ????return?walk

          w?=?ride_horse(ChangAn_distance)
          print(f'從長(zhǎng)安到秦州的總距離{w(100)}')
          print(w.__closure__)
          print(w.__closure__[0].cell_contents)
          print(f'從長(zhǎng)安到蘭州的總距離:{w(200)}')
          print(w.__closure__)
          print(w.__closure__[0].cell_contents)
          print(f'從長(zhǎng)安到?jīng)鲋莸目偩嚯x{w(300)}')
          print(w.__closure__)
          print(w.__closure__[0].cell_contents)


          65aa4abd39eb1754d3e879717463d88b.webp


          關(guān)于閉包與非閉包的區(qū)別,一張圖醒目:


          bdf3e612f2776febeb9100573c4a0eca.webp


          閉包之后是不會(huì)對(duì)全局變量的值進(jìn)行修改的!而非閉包內(nèi)部計(jì)算時(shí)影響了外部全局的變量!


          5

          關(guān)于閉包的面試題


          來(lái)看一比較基礎(chǔ)的,跟閉包相關(guān)的面試題:


          def?f1():
          ????a?=?100

          ????def?f2():
          ????????a?=?200
          ????????print(a)

          ????print(a)
          ????f2()
          ????print(a)

          f1()


          思考一下,最終會(huì)輸出什么呢?如下:


          a8653f5f2f9542a51737e38d92420e52.webp


          想一休哥一樣思考吧.......不解釋原因了!論動(dòng)手實(shí)踐的重要性!


          6

          總結(jié)


          總之大家要是想明白閉包是個(gè)怎么樣的概念以及其自身是怎么樣的一個(gè)存在,還是自己動(dòng)手多多實(shí)踐下,實(shí)踐出真理啊!閉包算是比較難的一個(gè)概念了,因?yàn)槠浔旧砭褪呛艹橄蟮拇嬖冢》凑P者是逼著自己完成的閉包篇,中途是真的想放棄,不太想寫(xiě)了.....堅(jiān)挺之后,收獲最大的還是自己!對(duì)這種“函數(shù)式編程”有了更深一步了解....


          至此完!

          瀏覽 74
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  学生妹久久一次 | 国产777视频 | 久久人妻免费视频 | 在线肏屄视频 | 日韩久久精品视频 |