簡(jiǎn)單語句可以在一個(gè)邏輯行內(nèi)表示,一些簡(jiǎn)單語句可以寫在一行由分號(hào)分隔,簡(jiǎn)單語句的句法如下:
simple_stmt ::= expression_stmt
| assert_stmt
| assignment_stmt
| augmented_assignment_stmt
| pass_stmt
| del_stmt
| return_stmt
| yield_stmt
| raise_stmt
| break_stmt
| continue_stmt
| import_stmt
| global_stmt
| nonlocal_stmt
表達(dá)式語句用于計(jì)算和寫一個(gè)值(多用在交互方式下), 或者(通常)調(diào)用過程(一個(gè)返回沒有意義的結(jié)果的函數(shù);
在Python中,過程返回None)。允許其它表達(dá)式語句的使用方法,有時(shí)也用的到。表達(dá)式語句的句法如下:
expression_stmt ::= expression_list
一個(gè)表達(dá)式語句要對(duì)該表達(dá)式列表(可能只是一個(gè)表達(dá)式)求值.
在交互模式下,如果該值不是空,就使用內(nèi)建函數(shù)repr()并自己將結(jié)果字符串寫入一行標(biāo)準(zhǔn)輸出,(除非結(jié)果為空,導(dǎo)致過程調(diào)用不會(huì)引起任何輸出。)
使用賦值把名字綁定(重新綁定)到值,以及修改可變對(duì)象的屬性或者項(xiàng)目:
assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression)
target_list ::= target ("," target)* [","]
target ::= identifier
| "(" target_list ")"
| "[" target_list "]"
| attributeref
| subscription
| slicing
| "*" target
(請(qǐng)參閱 attributeref、 subscription和slicing的基本語法定義部分。)
一個(gè)賦值語句要對(duì)該表達(dá)式列表求值(請(qǐng)記住這可以是一個(gè)表達(dá)式或者一個(gè)逗號(hào)分隔的列表,后者導(dǎo)出一個(gè)元組),然后從左到右地將對(duì)象結(jié)果依次賦給目的列表里的每個(gè)對(duì)象。
根據(jù)目標(biāo)(列表)的形式,賦值被遞歸地定義。當(dāng)目標(biāo)是一個(gè)可變對(duì)象的一部分時(shí)(一個(gè)屬性引用,subscription或者slicing),可變的對(duì)象必須最終執(zhí)行賦值,并確定其有效性,如果在賦值不可接受的情況下,可以引發(fā)出一個(gè)異常。被各種類型所遵循的規(guī)則和拋出的異常給出針對(duì)對(duì)象類型的定義(見標(biāo)準(zhǔn)的類型層次結(jié)構(gòu)部分)。
分配對(duì)象到目標(biāo)列表,括號(hào)或方括號(hào)內(nèi)為可選,遞歸地定義如下.
一個(gè)對(duì)象向單個(gè)目標(biāo)遞歸地賦值定義如下。
如果該目標(biāo)是一個(gè)標(biāo)志符(名字):
如果名字已經(jīng)被約束了它就被重新約束。這可能導(dǎo)致早先約束到該名字的對(duì)象的引用計(jì)數(shù)降為 零,導(dǎo)致釋放該對(duì)象的分配空間并調(diào)用其析構(gòu)器,如果它有一個(gè)的話。
如果目標(biāo)是一個(gè)用括號(hào)或者方括號(hào)括起來的目標(biāo)序列:該對(duì)象必須是具有和目標(biāo)序列中目標(biāo)個(gè)數(shù)同樣數(shù)目的迭代類型,且其子項(xiàng)從左到右地賦值給相應(yīng)目標(biāo)。
注意:如果對(duì)象是類的實(shí)例并且屬性引用的賦值操作發(fā)生在兩端,RHS 表達(dá)式,a.x既能訪問一個(gè)實(shí)例屬性,也能(如果沒有實(shí)例屬性存在)訪問一個(gè)類的屬性。這個(gè)LHS目標(biāo)a.x通常設(shè)定一個(gè)實(shí)例屬性,如果有必要就創(chuàng)建。因此,這兩個(gè)a.x的發(fā)生不需要涉及同樣的屬性,如果RHS表達(dá)式涉及到類的屬性,這個(gè)LHS會(huì)創(chuàng)建一個(gè)新的實(shí)例屬性作為賦值的目標(biāo)。
class Cls:
x = 3 # class variable
inst = Cls()
inst.x = inst.x + 1 # writes inst.x as 4 leaving Cls.x as 3
這個(gè)描述并不一定適用于描述符屬性,像屬性創(chuàng)建使用property()。
如果基礎(chǔ)對(duì)象是可變有序?qū)ο?例如列表),下標(biāo)必須給出一個(gè)整數(shù)。如果是負(fù)數(shù),序列的長度就被加上。最后的值必須是一個(gè)小于該序列長度的非負(fù)整數(shù),然后該序列就被請(qǐng)求將被賦對(duì)象賦值給 它帶那個(gè)指標(biāo)的項(xiàng)。如果指標(biāo)超出范圍,就會(huì)拋出IndexError異常(給一個(gè)用下標(biāo)引用的有序?qū)ο筚x 值不會(huì)給列表增添新項(xiàng))
如果基礎(chǔ)對(duì)象是一個(gè)映射對(duì)象(比如字典),下標(biāo)的類型必須和映射的鍵類型兼容,接著該映射就被 要求創(chuàng)建一個(gè)把下標(biāo)映射到被賦對(duì)象的鍵/數(shù)據(jù)對(duì)。這(操作)要不用新鍵值取代已存在的具有相同 鍵的鍵/值對(duì),要不插入一個(gè)新的鍵/值對(duì)(如果不存在相同的鍵)
用戶自定義的對(duì)象, ____setitem__ __()方法被調(diào)用以適當(dāng)?shù)膮?shù)。
CPython實(shí)現(xiàn)細(xì)節(jié):在當(dāng)前實(shí)現(xiàn)中,目標(biāo)對(duì)象的語法采取同一表達(dá)式,同時(shí)無效的語法在代碼生成階段內(nèi)被拒絕,導(dǎo)致更少的詳細(xì)的錯(cuò)誤消息輸出.
雖然賦值的定義隱含著左手邊和右手邊之間的重疊是“同時(shí)的”(比如,a, b = b, a交換兩個(gè)變量),在所賦值變量間的重疊卻是不安全的!在集合中出現(xiàn)從左到右分配變量間的重疊是不安全的,有時(shí)候值是混亂的,例如,下面的程序打印出[0, 2]:
x = [0, 1]
i = 0
i, x[i] = 1, 2 # i is updated, then x[i] is updated
print(x)
參見:
PEP 3132 - Extended Iterable Unpacking
The specification for the *target feature.
增量賦值就是在單條語句內(nèi)合并一個(gè)二元運(yùn)算和一個(gè)賦值語句。
augmented_assignment_stmt ::= augtarget augop (expression_list | yield_expression)
augtarget ::= identifier | attributeref | subscription | slicing
augop ::= "+=" | "-=" | "*=" | "/=" | "http://=" | "%=" | "**="
| ">>=" | "<<=" | "&=" | "^=" | "|="
(見最后三項(xiàng)符號(hào)基礎(chǔ)語法定義)
一條增量賦值語句對(duì)目標(biāo)(和一般的賦值語句不同,它不能是展開的對(duì)象)和表達(dá)式列表求值,執(zhí)行特定于兩個(gè)操作數(shù)的賦值類型的二元運(yùn)算,并將結(jié)果賦值給原先的目標(biāo)。目標(biāo)僅求值一次。
一條賦值語句,比如x+=1, 可以重寫為x=x+1,效果是類似的,但并不完全一樣。在增量版本中,x僅求值一次。而且,只要可能,實(shí)際的操作是就地進(jìn)行的,意思是并非創(chuàng)建一個(gè)新對(duì)象然后將其賦值給目標(biāo),而是修改老的對(duì)象。
不像普通的賦值語句,增量賦值先計(jì)算左邊再計(jì)算右邊。例如,a[i] += f (x) 首先查看a[i],然后它計(jì)算 f(x) 并執(zhí)行加法操作,最后,把結(jié)果寫入a[i]。
除了在一條語句中賦值給元組和多個(gè)對(duì)象的情況,增量賦值語句所完成的賦值用與普通賦值同樣的方式處理。類似地,除了可能的就地方式,由增量賦值執(zhí)行的二元運(yùn)算和普通的二元運(yùn)算也是一樣的。
For targets which are attribute references, the same caveat about class and instance attributes applies as for regular assignments.
assert語句是一個(gè)在程序中插入調(diào)試斷言的常用方法:
assert_stmt ::= "assert" expression ["," expression]
簡(jiǎn)單形式的, ”assert expression”, 等價(jià)于:
if __debug__:
if not expression: raise AssertionError
擴(kuò)展形式的, ”assert expression”, 等價(jià)于:
if __debug__:
if not expression1: raise AssertionError(expression2)
這些等價(jià)式假定了存在__debug__和AssertionError, 而不是具有相同名字的相應(yīng)內(nèi)建變量.在當(dāng)前實(shí)現(xiàn), 內(nèi)建變量 __debug__ 在普通情況下為True, 在要求優(yōu)化的情況下為False(命令行選項(xiàng)-O) 在編譯要求優(yōu)化時(shí), 當(dāng)前的代碼生成器不產(chǎn)生任何斷言語句的代碼.注意在錯(cuò)誤信息包括源代碼的作法是多余的; 因?yàn)樗鼈儠?huì)作為跟蹤回溯對(duì)象的一部分顯示。
給__debug__賦值是非法的,解釋器是在啟動(dòng)時(shí)讀取內(nèi)建變量的值的。
pass_stmt ::= "pass"
pass是一個(gè)空操作 - 當(dāng)執(zhí)行它,什么也不會(huì)做。它在句法上要求有一個(gè)語句時(shí)但不需要寫代碼時(shí)用到,例如:
def f(arg): pass # a function that does nothing (yet)
class C: pass # a class with no methods (yet)
del_stmt ::= "del" target_list
與賦值的定義方法類似,刪除也是遞歸的。下面是一些說明:
一個(gè)目標(biāo)表的遞歸刪除操作會(huì)從左到右地刪除其中的每個(gè)對(duì)象地.
刪除名字就是在本地命名空間和全局名字空間刪除掉該名字的綁定(必須存在), 從哪個(gè)名字空間刪除取決于該名字是否出現(xiàn)在其代碼塊的global語句中。如果名字沒有綁定,會(huì)拋出NameError異常。
對(duì)于屬性引用, 下標(biāo)和片斷的刪除會(huì)作用到相關(guān)的主元對(duì)象, 對(duì)片斷的刪除一般等價(jià)于對(duì)該片斷賦予相應(yīng) 類型的空片斷(但這也受被截為片斷的對(duì)象的限制).
3.2版本變化:之前如果嵌套數(shù)據(jù)塊中有空變量,在本地命名空間中刪除名字是不合法的。
return_stmt ::= "return" [expression_list]
return在句法上僅可以出現(xiàn)在嵌套的函數(shù)定義中, 不能出現(xiàn)在嵌套的類定義中.
如果給出了表達(dá)式表, 就計(jì)算其值, 否則就用None代替.
return的作用是離開當(dāng)前函數(shù)調(diào)用, 并以表達(dá)式表的值(或None)為返回值.
當(dāng)return放在具有?nally子句的try語句中, ?nally子句中的語句會(huì)在函數(shù)真正退出之前執(zhí)行一次.
在生成器函數(shù)中, return語句意味著生成器執(zhí)行完成,并且將會(huì)引發(fā)一個(gè)StopIteration異常。返回值(如果有的話)是作為StopIteration構(gòu)造方法的參數(shù),并且會(huì)變成StopIteration.value屬性。
yield_stmt ::= yield_expression
yield語句在語義上等同于yield表達(dá)式。yield語法被用來省略括號(hào),否則需要使用相同的yield表達(dá)式語句。例如,yield語句
yield <expr>
yield from <expr>
等同于yield表達(dá)式語句
(yield <expr>)
(yield from <expr>)
yield表達(dá)式和語句只有當(dāng)在定義生成器函數(shù)時(shí)被使用。只使用在生成器函數(shù)體中。在函數(shù)定義時(shí)使用yield,足夠?qū)е露x一個(gè)創(chuàng)建生成器函數(shù)而不是普通函數(shù)。
yield詳細(xì)的語法,參考yield表達(dá)式部分。
raise_stmt ::= "raise" [expression ["from" expression]]
如果不給出表達(dá)式,raise重新引發(fā)當(dāng)前范圍內(nèi)上次引發(fā)的異常。如果當(dāng)前范圍沒有可用的異常,會(huì)拋出RuntimeError異常,暗示出現(xiàn)錯(cuò)誤。
否則,raise使用第一個(gè)表達(dá)式作為異常對(duì)象求值。 對(duì)異常對(duì)象的第一個(gè)表達(dá)式求值。他必須是一個(gè)子類或者一個(gè)BaseException的實(shí)例。如果是一個(gè)類,當(dāng)實(shí)例化一個(gè)無參數(shù)類被需要的時(shí)候,異常實(shí)例將被獲取,
異常的類型是異常實(shí)例類,值是實(shí)例本身。
traceback對(duì)象通常被自動(dòng)創(chuàng)建,當(dāng)異常發(fā)生并且被附加到它的 traceback 屬性上。你可以創(chuàng)建異常并設(shè)置你自己的traceback,在第一步使用異常方法with _traceback()(這個(gè)方法返回相同的異常實(shí)例,traceback設(shè)置到他的參數(shù)中),就像:
raise Exception("foo occurred").with_traceback(tracebackobj)
from子句用于異常鏈接:如果給出,則第二個(gè)表達(dá)式必須是另一個(gè)異常類或?qū)嵗?,然后將附加到?__cause__ 屬性 (它是可寫)引發(fā)的異常。如果不處理引發(fā)的異常,則將打印兩個(gè)例外情況:
>>>>>>>>> try:
... print(1 / 0)
... except Exception as exc:
... raise RuntimeError("Something bad happened") from exc
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
ZeroDivisionError: int division or modulo by zero
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
RuntimeError: Something bad happened
一個(gè)類似的機(jī)制隱式工作如果里面的異常處理程序引發(fā)的異常或 finally 子句: 那么前一個(gè)異常附加作為新異常 __context__ 屬性:
>>>>>>>>> try:
... print(1 / 0)
... except:
... raise RuntimeError("Something bad happened")
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
ZeroDivisionError: int division or modulo by zero
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
RuntimeError: Something bad happened
更多異常信息見異常章節(jié),處理異常的信息Try語句章節(jié)。
break_stmt ::= "break"
break在句法上只能出現(xiàn)在for或while循環(huán)中, 但不能出現(xiàn)在循環(huán)中的函數(shù)定義或類定義中。
它中斷最內(nèi)層的循環(huán), 跳過其可選的else語句(如果有的話)。
如果for循環(huán)被break中斷, 它的循環(huán)控制對(duì)象還保持當(dāng)前值。
當(dāng)break放在具有?nally子句的try語句中, ?nally子句中的語句會(huì)在循環(huán)真正退出之前執(zhí)行一次。
continue_stmt ::= "continue"
continue在句法上只能出現(xiàn)在for或while循環(huán)中, 但不能出現(xiàn)在循環(huán)中的函數(shù)定義或類定義,或在循環(huán)內(nèi)部的finally子句。 它重新開 始最內(nèi)層的循環(huán)。
當(dāng)continue通行控制離開一個(gè)包含finally子句的try語句,finally子句執(zhí)行之前真的開始下一個(gè)循環(huán)周期。
import_stmt ::= "import" module ["as" name] ( "," module ["as" name] )*
| "from" relative_module "import" identifier ["as" name]
( "," identifier ["as" name] )*
| "from" relative_module "import" "(" identifier ["as" name]
( "," identifier ["as" name] )* [","] ")"
| "from" module "import" "*"
module ::= (identifier ".")* identifier
relative_module ::= "."* module | "."+
name ::= identifier
基本的import語句(不是from子句)執(zhí)行下面兩個(gè)步驟:
當(dāng)語句包含多個(gè)子句(由逗號(hào)分隔)分別對(duì)每個(gè)子句實(shí)施兩個(gè)步驟,就像子句被分隔成個(gè)體的import語句。
詳細(xì)的第一步,查找并加載模塊更詳細(xì)的描述在import system部分,它同樣描述可以被導(dǎo)入的模塊和各種類型的包,以及所有的鉤子可用于自定義導(dǎo)入系統(tǒng)。請(qǐng)注意在此步驟中的失敗可能表明該模塊無法找到,或者模塊初始化錯(cuò)誤,包含可執(zhí)行模塊的代碼錯(cuò)誤。
如果請(qǐng)求的模塊檢測(cè)到成功,它將提供局部空間中的三種方式中的一種:
如果模塊名后跟as,那么這個(gè)名字后as會(huì)直接綁定到導(dǎo)入的模塊。
如果沒有指定其他名字,并且被導(dǎo)入的是頂層模塊,模塊名被綁定在本地的命名空間作為引用導(dǎo)入模塊。
from方式的使用過程稍微復(fù)雜:
Examples: 例子:
import foo # foo imported and bound locally
import foo.bar.baz # foo.bar.baz imported, foo bound locally
import foo.bar.baz as fbb # foo.bar.baz imported and bound as fbb
from foo.bar import baz # foo.bar.baz imported and bound as baz
from foo import attr # foo imported and foo.attr bound as attr
如果標(biāo)識(shí)符列表由星號(hào)('*')取代,該模塊中定義的所有公共名稱,都在import語句所在的本地命名空間中被約束。
一個(gè)模塊所定義的“公共名稱”通過檢查該模塊的命名空間中的名為 __all__ 的變量決定。如果(該變量)有定義,它必須是一個(gè)字符串的有序序列,這些字符串是由該模塊定義或者導(dǎo)入的名字。在 __all__ 中給出的名字都被認(rèn)為是公共的且要求其存在。如果 __all__ 沒有定義,(該模塊的)公共名字的集合就包含所有在該模塊的名字空間中找到的,不以下劃線(” _ ”)起首的所有名字。
導(dǎo)入的通配符形式 - from module import *- 只允許模塊級(jí)別。試圖在類或者函數(shù)中使用它會(huì)拋出SyntaxError。
在指定你要導(dǎo)入的模塊時(shí),你并不一定要指定模塊的絕對(duì)名字。當(dāng)一個(gè)模塊或包是在其他包之內(nèi)時(shí),在同一個(gè)頂層包下,我們有可能使用不需指明包名的相對(duì)加載。通過在from之后的模塊或者包之前指定幾個(gè)句號(hào), 就可以在沒有精確名字的情況下,指定在當(dāng)前包層次中向上搜索多少層。一個(gè)句號(hào)代表包括導(dǎo)入操作所在模塊的當(dāng)前包。兩個(gè)句號(hào)代表上一個(gè)包層次,三個(gè)句號(hào)代表再上一個(gè)包層次,依次類推。所以,如果你在 pkg 包中執(zhí)行 from.import mod ,你就會(huì)導(dǎo)入pkg.mod。如果你從包 pkg.subpkg1 執(zhí)行 from ..subpkg2 import mod ,你就會(huì)導(dǎo)入 pkg.subpkg2.mod。相對(duì)導(dǎo)入的規(guī)范參見PEP328
函數(shù)importlib.import_module()用于支持要確定哪些模塊需要?jiǎng)討B(tài)加載的應(yīng)用程序。
future語句是一個(gè)編譯器指令,在指定的將來的Python版本應(yīng)該可以使用語法或語義去編譯一個(gè)特定的模塊,到那時(shí)Python特性將成為標(biāo)準(zhǔn)。
future語句旨在緩解未來版本Python的遷移,這類版本會(huì)引入語言不兼容的變化。在發(fā)布前它允許在每個(gè)模塊的基礎(chǔ)上使用新特性,發(fā)布后這個(gè)特性將成為標(biāo)準(zhǔn)。
future_statement ::= "from" "__future__" "import" feature ["as" name]
("," feature ["as" name])*
| "from" "__future__" "import" "(" feature ["as" name]
("," feature ["as" name])* [","] ")"
feature ::= identifier
name ::= identifier
future語句必須出現(xiàn)在模塊的頂部。唯一能出現(xiàn)在future前面的語句是:
Python 3.0 版本公認(rèn)的特性是absolute_import, division, generators, unicode_literals, print_function, nested_scopes和with_statement。他們都是多余的,因?yàn)樗麄兛偸窃趩⒂脿顟B(tài),同時(shí)只保持向后兼容的可編譯性。
在編程的時(shí)候future語句被識(shí)別出來,并且被特殊地對(duì)待:更改核心構(gòu)建的語義通常是通過生成不同的代碼來實(shí)現(xiàn)的。甚至有可能一個(gè)新的功能會(huì)引入一個(gè)新的不兼容的語法(比如一個(gè)新的保留字),在這種情況下,編譯器可能需要用區(qū)別對(duì)待的方式解析模塊。此類決定不能被推遲到運(yùn)行時(shí)。
對(duì)于任何發(fā)布的版本,編譯器明確已經(jīng)被定義的功能名稱,如果future語句包含未知功能時(shí),編譯器會(huì)提示編譯出錯(cuò)。
直接運(yùn)行語義作為任何導(dǎo)入語句都是相同的:這里有一個(gè)標(biāo)準(zhǔn)的__future__模塊,稍后會(huì)解釋,當(dāng)future語句被執(zhí)行的時(shí)候,將以通用方式被引入。
令人關(guān)注的運(yùn)行時(shí)語義取決于被future語句啟用的特定功能。
請(qǐng)注意,沒有什么特別的語句。
import __future__ [as name]
那個(gè)不是future語句;這是一個(gè)普通的導(dǎo)入語句沒有特殊的語義或語法的限制。
通過調(diào)用內(nèi)置函數(shù)exec()和compile()來編譯的代碼,此代碼在M模塊發(fā)起,并包含future語句,在默認(rèn)情況下,會(huì)結(jié)合future語句采用新的語法和語義。這可以由可選參數(shù)來控制去compile()——有關(guān)詳細(xì)信息,請(qǐng)參閱文檔的功能。
在交互式解析器提示符下鍵入future語句,重啟解析器器會(huì)話生效。如果解析器以-i選項(xiàng)開始,且是通過一個(gè)腳本名去執(zhí)行,同時(shí)這個(gè)腳本包含future語句,它將作用在交互會(huì)話中,在腳本執(zhí)行后開始。
參見:
PEP 236 - Back to the future
The original proposal for the future mechanism.
global_stmt ::= "global" identifier ("," identifier)*
global語句是對(duì)整個(gè)代碼塊都有作用的一個(gè)聲明. 它指出其所列的標(biāo)識(shí)符要解釋為全局的.如果某名字在本地命名空間中沒有定義, 就自動(dòng)使用相應(yīng)的全局名字. 沒有global是不可能手動(dòng)指定一個(gè)名字是全局的。
在global中出現(xiàn)的名字不能在global 之前的代碼中使用.
在global中出現(xiàn)的名字不能作為形參, 不能作為for循環(huán)的控制對(duì)象, 不能在類定義, 函數(shù)定義, import語句中出現(xiàn).
CPython詳細(xì)實(shí)現(xiàn):當(dāng)前實(shí)現(xiàn)不強(qiáng)制兩個(gè)限制,但程序不應(yīng)該濫用這種自由,作為將來的實(shí)現(xiàn)可能會(huì)強(qiáng)制他們或默默地改變程序的意義。
程序員注意: global是一個(gè)解析器的指示字. 它僅僅會(huì)對(duì)和global一起解析的代碼有效,尤其是,一個(gè)global語句被包含在字符串或者代碼對(duì)象提供內(nèi)建的exec()函數(shù),并不影響包含該函數(shù)調(diào)用的代碼塊,相同的機(jī)制也應(yīng)用于eval() 和compile() 函數(shù)。
nonlocal_stmt ::= "nonlocal" identifier ("," identifier)*
nonlocal語句引發(fā)列出的標(biāo)識(shí)符,適用于不包括global之外最近的封閉范圍,前一個(gè)綁定變量。這是重要的因?yàn)榻壎ǖ哪J(rèn)行為是首先搜索本地命名空間。該語句允許封裝的代碼綁定除了global(模塊)范圍之外,局部作用域的變量。
在nonlocal語句不同于那些在global語句中列出的名稱,必須引用到預(yù)先存在的封閉范圍中的綁定(不能明確的確定要在其中創(chuàng)建一個(gè)新綁定的范圍)。
在nonlocal語句中列出的名字,在本地范圍必須不和已經(jīng)存在的綁定沖突。
參見:
PEP 3104 - Access to Names in Outer Scopes
The specification for the nonlocal statement.