熱線電話:13121318867

登錄
首頁精彩閱讀Python基礎知識:什么是非局部語句?
Python基礎知識:什么是非局部語句?
2016-03-17
收藏
本文首發于微信公眾號號“編程派”。微信搜索“編程派”,獲取更多Python編程一手教程及優質資源吧。

有同學曾在微信中問小編什么是非局部語句(nonlocal statement),本文就是對此的回答,希望沒有發的太晚。

非局部語句是Python 3.x中新引入的特性。官方文檔中的說法是,非局部語句可以讓所列的標識符(identifier)指向最近的嵌套作用域(enclosing scope)中已經綁定過的變量,全局變量除外。

如果沒有非局部語句

一般來說,嵌套函數對于其外層作用域中的變量是有訪問權限的。


>>> def outside():
        msg = "Outside!"

        def inside():
            print(msg)

        inside()
       print(msg)
>>> outside()
Outside!
Outside!

我們在outside函數中聲明了msg變量,并賦值為“Outside!”。然后,在inside函數中打印msg的值。結果證明,inside成功獲得了外層作用域中msg的值。

但是如果我們想給外層作用域中的變量賦值時,是不是按照平常的賦值操作就可以修改它的值呢?


>>> def outside():
        msg = "Outside!"
        def inside():
            msg = "Inside!"
            print(msg)
        inside()
       print(msg)
>>> outside()
Inside! # inside函數打印的msg
Outside! # outside函數打印的msg

在inside函數中,我們想給msg變量賦值為"Inside!"。運行outside時,inside函數中msg的值為"Inside!",但是在outside函數中卻保留了原先的值!

之所以出現這個情況,是因為在inside函數中,Python實際上并沒有為之前已經創建的msg變量賦值,而是在inside函數的局部作用域(local scope)中創建了一個名叫msg的新變量,但是這樣就和外層作用域(outer scope)中的變量重名了。

這說明,嵌套函數對外層作用域中的變量其實只有只讀訪問權限。如果我們在這個示例中的inside函數的頂部再加一個print(msg)語句,那么就會出現UnboundLocalError: local variable 'msg' referenced before assignment這個錯誤。

非局部語句的引入,就是要盡量減少這種變量名沖突情況的出現,同時也讓嵌套函數更加方便的操作外層函數中的變量。更加詳細的原因,請看參考資料部分的PEP-3104。

使用非局部語句之后

接下來,我們引入nonlocal語句。


>>> def outside():
        msg = "Outside!"
        def inside():
            nonlocal msg
            msg = "Inside!"
            print(msg)
        inside()
       print(msg)
>>> outside()
Inside!
Inside!

現在,我們在inside函數的頂部添加了nonlocal msg語句。這個語句的作用,就是告訴Python解釋器在碰到為msg賦值的語句時,應該向外層作用域的變量賦值,而不是聲明一個重名的新變量。這樣,兩個函數的打印結果就一致了。

nonlocal的用法和global非常類似,只是前者針對的是外層函數作用域的變量,后者針對的則是全局作用域的變量。

什么時候該使用非局部語句

有時候,你可能會疑惑什么時候才應該使用nonlocal。以下面的函數為例:


>>> def outside():
       d = {"outside": 1} 
       def inside():
            d["inside"] = 2
            print(d)
        inside()
       print(d)
>>> outside()
{'inside': 2, 'outside': 1}
{'inside': 2, 'outside': 1}

你可能會想,因為沒有使用nonlocal,inside函數中往字典d中插入的"inside": 2鍵值對(key-value pair)不會體現在outside函數中。你這么想挺合理,但卻是錯的。因為字典插入并不是賦值操作,而是方法調用(method call)。事實上,往字典中插入一個鍵值對相當于調用字典對象中的__setitem__方法。


>>> d = {}
>>> d.__setitem__("inside", 2)
>>> d
{'inside': 2}

所以,這個示例中我們可以不使用nonlocal,就能直接操作外層作用域中的變量。

小結

其實在許多Python程序中,很少用到非局部語句。但是,有了這種語句之后,我們就可以減少不同作用域之間變量名的沖突。非局部語句,也讓我們更加容易地訪問、操作外層作用域中的變量。不過,這在一定程度上也讓語法變得更加復雜。

有關變量、語句等術語的基礎知識,還可以參考《Think Python 2e》的第二章:量、表達式和語句。

參考資料

請點擊閱讀原文,查看相關鏈接。

Simple Statements
PEP-3104
Global-Nonlocal
PyTips 0x04
A Quick Guide to nonlocal in Python 3

數據分析咨詢請掃描二維碼

若不方便掃碼,搜微信號:CDAshujufenxi

數據分析師資訊
更多

OK
客服在線
立即咨詢
日韩人妻系列无码专区视频,先锋高清无码,无码免费视欧非,国精产品一区一区三区无码
客服在線
立即咨詢