1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Python 為什么引入這兩個關(guān)鍵詞

        共 3211字,需瀏覽 7分鐘

         ·

        2021-07-12 10:16

        ↑↑↑關(guān)注后"星標(biāo)"簡說Python

        人人都可以簡單入門Python、爬蟲、數(shù)據(jù)分析
         簡說Python推薦 

        來源: Python中文社區(qū)

        作者:鞏慶奎



        啥是 global 和 nonlocal

        Python 支持的關(guān)鍵詞里,global 和 nonlocal 初學(xué)者接觸的少,不知道是做什么用的;一些人雖然知道它們的作用,但對為什么要引入這兩個關(guān)鍵詞則有些不知其所以然。

        粗淺地說,global 和 nonlocal 是為了在函數(shù)中修改全局和閉包變量而引入的關(guān)鍵字。

        本文用代碼一點(diǎn)點(diǎn)分析引入 global 和 nonlocal 的原因。

        一個奇怪的現(xiàn)象

        下面,讓我們做一個測試。

        g =1def fun():    g = 2    return g print(fun(),g)

        一般地,我們認(rèn)為結(jié)果應(yīng)該為 2,2。這一點(diǎn)學(xué)過其他語言如 Java、c 的同學(xué)尤其認(rèn)同。

        但讓我們跑起來,可以看到結(jié)果為 2,1。也就是說,函數(shù)沒有改變?nèi)肿兞?g。

        這很奇怪,究其原因是因?yàn)椋?/p>

        ?Python 認(rèn)為所有 = 賦值都是在當(dāng)前作用域新建變量。? 當(dāng)我們在程序中 g = 1 時,表示當(dāng)前全局作用域建立 g,賦值 1。? 當(dāng)我們在函數(shù)中 g = 2 時,表示當(dāng)前局部作用域建立 g,賦值 2。

        使用 dis.dis(fun) 分析 fun 函數(shù)源代碼:

         16           0 LOAD_CONST               1 (2)              2 STORE_FAST               0 (g) 17           4 LOAD_FAST                0 (g)              6 RETURN_VALUE

        可見,第 2 條指令 STORE_FAST,這是存儲到局部變量的命令。

        所以,函數(shù)中實(shí)際操作的是局部變量。

        還有更甚的例子如下,大家猜測下執(zhí)行結(jié)果。

        g =1def fun():    g += 1    return gprint(fun(),g) 

        根據(jù)上文,我們知道函數(shù)不會改變?nèi)肿兞?g,那么結(jié)果應(yīng)該是 2,1,這次總算對了吧?

        很抱歉,當(dāng)執(zhí)行到 g += 1 時,系統(tǒng)報(bào)錯:UnboundLocalError: local variable 'g' referenced before assignment。

        仔細(xì)觀察錯誤,local variable 'g',這里的 g 仍然被視為局部變量:沒有定義(=賦值),就直接 inplace add,當(dāng)然要報(bào)錯。

        也就是說,所有在局部作用域中對全局變量的賦值、原位賦值都會失敗。唯有如下函數(shù)給我們帶來一絲安慰。

        g =1def fun():    return gprint(fun(),g) 

        結(jié)果 1,1,總算還有個正常的:在局部作用域中引用全局作用域變量正常。

        那當(dāng)我必須修改全局變量時,該怎么辦呢?

        global 的引入和分析

        這就是 global 引入的理由了,將全局變量擴(kuò)展到函數(shù)中來,使函數(shù)可以修改全局變量。

        g =1def fun():    global g    g = 2    return gprint(fun(),g) 

        結(jié)果為 2,2,函數(shù)修改了全局變量。我們來看 dis.dis(fun) 的反匯編代碼。

         37           0 LOAD_CONST               1 (2)              2 STORE_GLOBAL             0 (g) 38           4 LOAD_GLOBAL              0 (g)              6 RETURN_VALUE

        第 2 條指令,STORE_GLOBAL 是將常量 2 賦值給全局變量 g,異于上例中的 STORE_FAST指令對局部變量操作。

        故此,我們得出結(jié)論:當(dāng)在函數(shù)中讀取全局變量時,可以直接使用。但如果需要修改全局變量值,則需要在變量前加上 global 來修飾。

        nonlocal 的引入

        同樣地,當(dāng)我們書寫嵌套函數(shù),需要對閉包中的變量進(jìn)行修改操作時,我們也需要引入 nonlocal 關(guān)鍵字。

        如下函數(shù)中,我們定義了閉包,閉包中的變量 e,試圖在內(nèi)嵌函數(shù)中進(jìn)行修改,但沒有使用 nonlocal 關(guān)鍵字聲明 e。

        def outer():    e = 1    def inner():        e = 2        return e    return inner

        參照上例,我們知道這種修改是徒勞的——因?yàn)榭捶磪R編代碼 dis.dis(outer()) 可知:

         63           0 LOAD_CONST               1 (2)              2 STORE_FAST               0 (e) 64           4 LOAD_FAST                0 (e)              6 RETURN_VALUE

        第 2 條指令 STORE_FAST,操作局部變量,也就是說 inner 里的 e,仍然被視為局部變量。

        雷同于上例的 global,這里使用 nonlocal 來在內(nèi)嵌函數(shù) inner 中修改閉包變量 e。

        def outer():    e = 1    def inner():        nonlocal e        e = 2        return e    return inner

        查看此時的反匯編代碼 dis.dis(outer()) 可知:

         78           0 LOAD_CONST               1 (2)              2 STORE_DEREF              0 (e) 79           4 LOAD_DEREF               0 (e)              6 RETURN_VALUE

        第 2 條指令 STORE_DEREF,操作的是閉包變量,也就是說 inner 里的 e,是可以修改的閉包中的 e。

        總結(jié)

        本文通過分析函數(shù)對全局變量和閉包變量的讀、寫操作,借助于反匯編字節(jié)碼分析,認(rèn)清了 global 和 nonlocal 關(guān)鍵字的用法,對其引入和作用有了較為深刻認(rèn)識。

        作者:鞏慶奎,大奎,對計(jì)算機(jī)、電子信息工程感興趣。gongqingkui at 126.com


        --END--

        老表薦書

        圖書介紹Python數(shù)據(jù)科學(xué)實(shí)踐本書由狗熊會推出的一本利用Python介紹數(shù)據(jù)科學(xué)基本過程的著作。本書以Python語言為基礎(chǔ),介紹利用Python進(jìn)行數(shù)據(jù)科學(xué)研究與商業(yè)分析的全貌。其核心的設(shè)計(jì)理念是通過經(jīng)典的商業(yè)應(yīng)用案例對數(shù)據(jù)爬取、數(shù)據(jù)存儲、數(shù)據(jù)清洗、數(shù)據(jù)建模的核心Python模塊做相應(yīng)的介紹。

        掃碼即可加我微信

        老表朋友圈經(jīng)常有贈書/紅包福利活動


        學(xué)習(xí)更多:
        整理了我開始分享學(xué)習(xí)筆記到現(xiàn)在超過250篇優(yōu)質(zhì)文章,涵蓋數(shù)據(jù)分析、爬蟲、機(jī)器學(xué)習(xí)等方面,別再說不知道該從哪開始,實(shí)戰(zhàn)哪里找了

        優(yōu)秀的讀者都知道,“點(diǎn)贊”傳統(tǒng)美德不能丟 

        瀏覽 31
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

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

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            伊人婷婷影院 | 日日骚av | 大香蕉熟女性爱视频 | 一区二区三区精品无码 | 西欧一级片 | 美女逼逼网站 | 久久久久久中文字幕 | 欧美黑人狂躁少妇无码中文字幕 | 亚洲精品秘 一区二区 | 狠狠色婷婷久久一区二区牛牛影视 |