7. 簡(jiǎn)單語(yǔ)句?
簡(jiǎn)單語(yǔ)句由一個(gè)單獨的邏輯行構成。 多條簡(jiǎn)單語(yǔ)句可以存在于同一行內并以分號分隔。 簡(jiǎn)單語(yǔ)句的句法為:
simple_stmt ::=expression_stmt
|assert_stmt
|assignment_stmt
|augmented_assignment_stmt
|annotated_assignment_stmt
|pass_stmt
|del_stmt
|return_stmt
|yield_stmt
|raise_stmt
|break_stmt
|continue_stmt
|import_stmt
|future_stmt
|global_stmt
|nonlocal_stmt
7.1. 表達式語(yǔ)句?
表達式語(yǔ)句用于計算和寫(xiě)入值(大多是在交互模式下),或者(通常情況)調用一個(gè)過(guò)程 (過(guò)程就是不返回有意義結果的函數;在 Python 中,過(guò)程的返回值為 None
)。 表達式語(yǔ)句的其他使用方式也是允許且有特定用處的。 表達式語(yǔ)句的句法為:
expression_stmt ::= starred_expression
表達式語(yǔ)句會(huì )對指定的表達式列表(也可能為單一表達式)進(jìn)行求值。
在交互模式下,如果結果值不為 None
,它會(huì )通過(guò)內置的 repr()
函數轉換為一個(gè)字符串,該結果字符串將以單獨一行的形式寫(xiě)入標準輸出(例外情況是如果結果為 None
,則該過(guò)程調用不產(chǎn)生任何輸出。)
7.2. 賦值語(yǔ)句?
賦值語(yǔ)句用于將名稱(chēng)(重)綁定到特定值,以及修改屬性或可變對象的成員項:
assignment_stmt ::= (target_list
"=")+ (starred_expression
|yield_expression
) target_list ::=target
(","target
)* [","] target ::=identifier
| "(" [target_list
] ")" | "[" [target_list
] "]" |attributeref
|subscription
|slicing
| "*"target
(請參閱 原型 一節了解 屬性引用, 抽取 和 切片 的句法定義。)
賦值語(yǔ)句會(huì )對指定的表達式列表進(jìn)行求值(注意這可能為單一表達式或是由逗號分隔的列表,后者將產(chǎn)生一個(gè)元組)并將單一結果對象從左至右逐個(gè)賦值給目標列表。
賦值是根據目標(列表)的格式遞歸地定義的。 當目標為一個(gè)可變對象(屬性引用、抽取或切片)的組成部分時(shí),該可變對象必須最終執行賦值并決定其有效性,如果賦值操作不可接受也可能引發(fā)異常。 各種類(lèi)型可用的規則和引發(fā)的異常通過(guò)對象類(lèi)型的定義給出(參見(jiàn) 標準類(lèi)型層級結構 一節)。
對象賦值的目標對象可以包含于圓括號或方括號內,具體操作按以下方式遞歸地定義。
如果目標列表為后面不帶逗號、可以包含于圓括號內的單一目標,則將對象賦值給該目標。
Else:
如果目標列表包含一個(gè)帶有星號前綴的目標,這稱(chēng)為“加星”目標:則該對象至少必須為與目標列表項數減一相同項數的可迭代對象。 該可迭代對象前面的項將按從左至右的順序被賦值給加星目標之前的目標。 該可迭代對象末尾的項將被賦值給加星目標之后的目標。 然后該可迭代對象中剩余項的列表將被賦值給加星目標(該列表可以為空)。
否則:該對象必須為具有與目標列表相同項數的可迭代對象,這些項將按從左至右的順序被賦值給對應的目標。
對象賦值給單個(gè)目標的操作按以下方式遞歸地定義。
如果目標為標識符(名稱(chēng)):
如果該名稱(chēng)未出現于當前代碼塊的
global
或nonlocal
語(yǔ)句中:該名稱(chēng)將被綁定到當前局部命名空間的對象。否則:該名稱(chēng)將被分別綁定到全局命名空間或由
nonlocal
所確定的外層命名空間的對象。
如果該名稱(chēng)已經(jīng)被綁定則將被重新綁定。 這可能導致之前被綁定到該名稱(chēng)的對象的引用計數變?yōu)榱?,造成該對象進(jìn)入釋放過(guò)程并調用其析構器(如果存在)。
如果該對象為屬性引用:引用中的原型表達式會(huì )被求值。 它應該產(chǎn)生一個(gè)具有可賦值屬性的對象;否則將引發(fā)
TypeError
。 該對象會(huì )被要求將可賦值對象賦值給指定的屬性;如果它無(wú)法執行賦值,則會(huì )引發(fā)異常 (通常應為AttributeError
但并不強制要求)。注意:如果該對象為類(lèi)實(shí)例并且屬性引用在賦值運算符的兩側都出現,則右側表達式
a.x
可以訪(fǎng)問(wèn)實(shí)例屬性或(如果實(shí)例屬性不存在)類(lèi)屬性。 左側目標a.x
將總是設定為實(shí)例屬性,并在必要時(shí)創(chuàng )建該實(shí)例屬性。 因此a.x
的兩次出現不一定指向相同的屬性:如果右側表達式指向一個(gè)類(lèi)屬性,則左側會(huì )創(chuàng )建一個(gè)新的實(shí)例屬性作為賦值的目標:class Cls: x = 3 # class variable inst = Cls() inst.x = inst.x + 1 # writes inst.x as 4 leaving Cls.x as 3
此描述不一定作用于描述器屬性,例如通過(guò)
property()
創(chuàng )建的特征屬性。如果目標為一個(gè)抽取項:引用中的原型表達式會(huì )被求值。 它應當產(chǎn)生一個(gè)可變序列對象(例如列表)或一個(gè)映射對象(例如字典)。 接下來(lái),該抽取表達式會(huì )被求值。
如果原型為一個(gè)可變序列對象(例如列表),抽取應產(chǎn)生一個(gè)整數。 如其為負值,則再加上序列長(cháng)度。 結果值必須為一個(gè)小于序列長(cháng)度的非負整數,序列將把被賦值對象賦值給該整數指定索引號的項。 如果索引超出范圍,將會(huì )引發(fā)
IndexError
(給被抽取序列賦值不能向列表添加新項)。如果原型為一個(gè)映射對象(例如字典),抽取必須具有與該映射的鍵類(lèi)型相兼容的類(lèi)型,然后映射中會(huì )創(chuàng )建一個(gè)將抽取映射到被賦值對象的鍵/值對。 這可以是替換一個(gè)現有鍵/值對并保持相同鍵值,也可以是插入一個(gè)新鍵/值對(如果具有相同值的鍵不存在)。
對于用戶(hù)定義對象,會(huì )調用
__setitem__()
方法并附帶適當的參數。如果目標為一個(gè)切片:引用中的原型表達式會(huì )被求值。 它應當產(chǎn)生一個(gè)可變序列對象(例如列表)。 被賦值對象應當是一個(gè)相同類(lèi)型的序列對象。 接下來(lái),下界與上界表達式如果存在的話(huà)將被求值;默認值分別為零和序列長(cháng)度。 上下邊界值應當為整數。 如果某一邊界為負值,則會(huì )加上序列長(cháng)度。 求出的邊界會(huì )被裁剪至介于零和序列長(cháng)度的開(kāi)區間中。 最后,將要求序列對象以被賦值序列的項替換該切片。 切片的長(cháng)度可能與被賦值序列的長(cháng)度不同,這會(huì )在目標序列允許的情況下改變目標序列的長(cháng)度。
CPython implementation detail: 在當前實(shí)現中,目標的句法被當作與表達式的句法相同,無(wú)效的句法會(huì )在代碼生成階段被拒絕,導致不太詳細的錯誤信息。
雖然賦值的定義意味著(zhù)左手邊與右手邊的重疊是“同時(shí)”進(jìn)行的(例如 a, b = b, a
會(huì )交換兩個(gè)變量的值),但在賦值給變量的多項集 之內 的重疊是從左至右進(jìn)行的,這有時(shí)會(huì )令人混淆。 例如,以下程序將會(huì )打印出 [0, 2]
:
x = [0, 1]
i = 0
i, x[i] = 1, 2 # i is updated, then x[i] is updated
print(x)
參見(jiàn)
- PEP 3132 - 擴展的可迭代對象拆包
對
*target
特性的規范說(shuō)明。
7.2.1. 增強賦值語(yǔ)句?
增強賦值語(yǔ)句就是在單個(gè)語(yǔ)句中將二元運算和賦值語(yǔ)句合為一體:
augmented_assignment_stmt ::=augtarget
augop
(expression_list
|yield_expression
) augtarget ::=identifier
|attributeref
|subscription
|slicing
augop ::= "+=" | "-=" | "*=" | "@=" | "/=" | "http://=" | "%=" | "**=" | ">>=" | "<<=" | "&=" | "^=" | "|="
(請參閱 原型 一節了解最后三種符號的句法定義。)
增強賦值語(yǔ)句將對目標和表達式列表求值(與普通賦值語(yǔ)句不同的是,前者不能為可迭代對象拆包),對兩個(gè)操作數相應類(lèi)型的賦值執行指定的二元運算,并將結果賦值給原始目標。 目標僅會(huì )被求值一次。
增強賦值語(yǔ)句例如 x += 1
可以改寫(xiě)為 x = x + 1
獲得類(lèi)似但并非完全等價(jià)的效果。 在增強賦值的版本中,x
僅會(huì )被求值一次。 而且,在可能的情況下,實(shí)際的運算是 原地 執行的,也就是說(shuō)并不是創(chuàng )建一個(gè)新對象并將其賦值給目標,而是直接修改原對象。
不同于普通賦值,增強賦值會(huì )在對右手邊求值 之前 對左手邊求值。 例如,a[i] += f(x)
首先查找 a[i]
,然后對 f(x)
求值并執行加法操作,最后將結果寫(xiě)回到 a[i]
。
除了在單個(gè)語(yǔ)句中賦值給元組和多個(gè)目標的例外情況,增強賦值語(yǔ)句的賦值操作處理方式與普通賦值相同。 類(lèi)似地,除了可能存在 原地 操作行為的例外情況,增強賦值語(yǔ)句執行的二元運算也與普通二元運算相同。
對于屬性引用類(lèi)目標,針對常規賦值的 關(guān)于類(lèi)和實(shí)例屬性的警告 也同樣適用。
7.2.2. 帶標注的賦值語(yǔ)句?
標注 賦值就是在單個(gè)語(yǔ)句中將變量或屬性標注和可選的賦值語(yǔ)句合為一體:
annotated_assignment_stmt ::=augtarget
":"expression
["=" (starred_expression
|yield_expression
)]
與普通 賦值語(yǔ)句 的差別在于僅允許單個(gè)目標。
對于將簡(jiǎn)單名稱(chēng)作為賦值目標的情況,如果是在類(lèi)或模塊作用域中,標注會(huì )被求值并存入一個(gè)特殊的類(lèi)或模塊屬性 __annotations__
中,這是一個(gè)將變量名稱(chēng)(如為私有會(huì )被移除)映射到被求值標注的字典。 此屬性為可寫(xiě)并且在類(lèi)或模塊體開(kāi)始執行時(shí)如果靜態(tài)地發(fā)現標注就會(huì )自動(dòng)創(chuàng )建。
對于將表達式作為賦值目標的情況,如果是在類(lèi)或模塊作用域中,標注會(huì )被求值,但不會(huì )保存。
如果一個(gè)名稱(chēng)在函數作用域內被標注,則該名稱(chēng)為該作用域的局部變量。 標注絕不會(huì )在函數作用域內被求值和保存。
如果存在右手邊,帶標注的賦值會(huì )在對標注求值之前(如果適用)執行實(shí)際的賦值。 如果用作表達式目標的右手邊不存在,則解釋器會(huì )對目標求值,但最后的 __setitem__()
或 __setattr__()
調用除外。
參見(jiàn)
在 3.8 版更改: 現在帶有標注的賦值允許在右邊以同樣的表達式作為常規賦值。 之前,某些表達式(例如未加圓括號的元組表達式)會(huì )導致語(yǔ)法錯誤。
7.3. assert
語(yǔ)句?
assert 語(yǔ)句是在程序中插入調試性斷言的簡(jiǎn)便方式:
assert_stmt ::= "assert"expression
[","expression
]
簡(jiǎn)單形式 assert expression
等價(jià)于
if __debug__:
if not expression: raise AssertionError
擴展形式 assert expression1, expression2
等價(jià)于
if __debug__:
if not expression1: raise AssertionError(expression2)
以上等價(jià)形式假定 __debug__
和 AssertionError
指向具有指定名稱(chēng)的內置變量。 在當前實(shí)現中,內置變量 __debug__
在正常情況下為 True
,在請求優(yōu)化時(shí)為 False
(對應命令行選項為 -O
)。 如果在編譯時(shí)請求優(yōu)化,當前代碼生成器不會(huì )為 assert 語(yǔ)句發(fā)出任何代碼。 請注意不必在錯誤信息中包含失敗表達式的源代碼;它會(huì )被作為棧追蹤的一部分被顯示。
賦值給 __debug__
是非法的。 該內置變量的值會(huì )在解釋器啟動(dòng)時(shí)確定。
7.4. pass
語(yǔ)句?
pass_stmt ::= "pass"
pass
是一個(gè)空操作 --- 當它被執行時(shí),什么都不發(fā)生。 它適合當語(yǔ)法上需要一條語(yǔ)句但并不需要執行任何代碼時(shí)用來(lái)臨時(shí)占位,例如:
def f(arg): pass # a function that does nothing (yet)
class C: pass # a class with no methods (yet)
7.5. del
語(yǔ)句?
del_stmt ::= "del" target_list
刪除是遞歸定義的,與賦值的定義方式非常類(lèi)似。 此處不再詳細說(shuō)明,只給出一些提示。
目標列表的刪除將從左至右遞歸地刪除每一個(gè)目標。
名稱(chēng)的刪除將從局部或全局命名空間中移除該名稱(chēng)的綁定,具體作用域的確定是看該名稱(chēng)是否有在同一代碼塊的 global
語(yǔ)句中出現。 如果該名稱(chēng)未被綁定,將會(huì )引發(fā) NameError
。
屬性引用、抽取和切片的刪除會(huì )被傳遞給相應的原型對象;刪除一個(gè)切片基本等價(jià)于賦值為一個(gè)右側類(lèi)型的空切片(但即便這一點(diǎn)也是由切片對象決定的)。
在 3.2 版更改: 在之前版本中,如果一個(gè)名稱(chēng)作為被嵌套代碼塊中的自由變量出現,則將其從局部命名空間中刪除是非法的。
7.6. return
語(yǔ)句?
return_stmt ::= "return" [expression_list
]
return
在語(yǔ)法上只會(huì )出現于函數定義所嵌套的代碼,不會(huì )出現于類(lèi)定義所嵌套的代碼。
如果提供了表達式列表,它將被求值,否則以 None
替代。
return
會(huì )離開(kāi)當前函數調用,并以表達式列表 (或 None
) 作為返回值。
當 return
將控制流傳出一個(gè)帶有 finally
子句的 try
語(yǔ)句時(shí),該 finally
子句會(huì )先被執行然后再真正離開(kāi)該函數。
在一個(gè)生成器函數中,return
語(yǔ)句表示生成器已完成并將導致 StopIteration
被引發(fā)。 返回值(如果有的話(huà))會(huì )被當作一個(gè)參數用來(lái)構建 StopIteration
并成為 StopIteration.value
屬性。
在一個(gè)異步生成器函數中,一個(gè)空的 return
語(yǔ)句表示異步生成器已完成并將導致 StopAsyncIteration
被引發(fā)。 一個(gè)非空的 return
語(yǔ)句在異步生成器函數中會(huì )導致語(yǔ)法錯誤。
7.7. yield
語(yǔ)句?
yield_stmt ::= yield_expression
yield
語(yǔ)句在語(yǔ)義上等同于 yield 表達式。 yield 語(yǔ)句可用來(lái)省略在使用等效的 yield 表達式語(yǔ)句時(shí)所必須的圓括號。 例如,以下 yield 語(yǔ)句
yield <expr>
yield from <expr>
等同于以下 yield 表達式語(yǔ)句
(yield <expr>)
(yield from <expr>)
yield 表達式和語(yǔ)句僅在定義 generator 函數時(shí)使用,并且僅被用于生成器函數的函數體內部。 在函數定義中使用 yield 就足以使得該定義創(chuàng )建的是生成器函數而非普通函數。
7.8. raise
語(yǔ)句?
raise_stmt ::= "raise" [expression
["from"expression
]]
If no expressions are present, raise
re-raises the
exception that is currently being handled, which is also known as the active exception.
If there isn't currently an active exception, a RuntimeError
exception is raised
indicating that this is an error.
否則的話(huà),raise
會(huì )將第一個(gè)表達式求值為異常對象。 它必須為 BaseException
的子類(lèi)或實(shí)例。 如果它是一個(gè)類(lèi),當需要時(shí)會(huì )通過(guò)不帶參數地實(shí)例化該類(lèi)來(lái)獲得異常的實(shí)例。
異常的 類(lèi)型 為異常實(shí)例的類(lèi),值 為實(shí)例本身。
A traceback object is normally created automatically when an exception is raised
and attached to it as the __traceback__
attribute, which is writable.
You can create an exception and set your own traceback in one step using the
with_traceback()
exception method (which returns the
same exception instance, with its traceback set to its argument), like so:
raise Exception("foo occurred").with_traceback(tracebackobj)
from
子句用于異常串連:如果有該子句,則第二個(gè) 表達式 必須為另一個(gè)異常類(lèi)或實(shí)例。 如果第二個(gè)表達式是一個(gè)異常實(shí)例,它將作為可寫(xiě)的 __cause__
屬性被關(guān)聯(lián)到所引發(fā)的異常。 如果該表達式是一個(gè)異常類(lèi),這個(gè)類(lèi)將被實(shí)例化且所生成的異常實(shí)例將作為 __cause__
屬性被關(guān)聯(lián)到所引發(fā)的異常。 如果所引發(fā)的異常未被處理,則兩個(gè)異常都將被打印出來(lái):
>>> 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: division 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
A similar mechanism works implicitly if a new exception is raised when
an exception is already being handled. An exception may be handled
when an except
or finally
clause, or a
with
statement, is used. The previous exception is then
attached as the new exception's __context__
attribute:
>>> try:
... print(1 / 0)
... except:
... raise RuntimeError("Something bad happened")
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
ZeroDivisionError: division 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
異常串連可通過(guò)在 from
子句中指定 None
來(lái)顯式地加以抑制:
>>> try:
... print(1 / 0)
... except:
... raise RuntimeError("Something bad happened") from None
...
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
RuntimeError: Something bad happened
有關(guān)異常的更多信息可在 異常 一節查看,有關(guān)處理異常的信息可在 try 語(yǔ)句 一節查看。
在 3.3 版更改: None
現在允許被用作 raise X from Y
中的 Y
。
3.3 新版功能: 使用 __suppress_context__
屬性來(lái)抑制異常上下文的自動(dòng)顯示。
在 3.11 版更改: If the traceback of the active exception is modified in an except
clause, a subsequent raise
statement re-raises the exception with the
modified traceback. Previously, the exception was re-raised with the
traceback it had when it was caught.
7.9. break
語(yǔ)句?
break_stmt ::= "break"
break
在語(yǔ)法上只會(huì )出現于 for
或 while
循環(huán)所嵌套的代碼,但不會(huì )出現于該循環(huán)內部的函數或類(lèi)定義所嵌套的代碼。
它會(huì )終結最近的外層循環(huán),如果循環(huán)有可選的 else
子句,也會(huì )跳過(guò)該子句。
如果一個(gè) for
循環(huán)被 break
所終結,該循環(huán)的控制目標會(huì )保持其當前值。
當 break
將控制流傳出一個(gè)帶有 finally
子句的 try
語(yǔ)句時(shí),該 finally
子句會(huì )先被執行然后再真正離開(kāi)該循環(huán)。
7.10. continue
語(yǔ)句?
continue_stmt ::= "continue"
continue
在語(yǔ)法上只會(huì )出現于 for
或 while
循環(huán)所嵌套的代碼中,但不會(huì )出現于該循環(huán)內部的函數或類(lèi)定義中。 它會(huì )繼續執行最近的外層循環(huán)的下一個(gè)輪次。
當 continue
將控制流傳出一個(gè)帶有 finally
子句的 try
語(yǔ)句時(shí),該 finally
子句會(huì )先被執行然后再真正開(kāi)始循環(huán)的下一個(gè)輪次。
7.11. import
語(yǔ)句?
import_stmt ::= "import"module
["as"identifier
] (","module
["as"identifier
])* | "from"relative_module
"import"identifier
["as"identifier
] (","identifier
["as"identifier
])* | "from"relative_module
"import" "("identifier
["as"identifier
] (","identifier
["as"identifier
])* [","] ")" | "from"relative_module
"import" "*" module ::= (identifier
".")*identifier
relative_module ::= "."*module
| "."+
基本的 import 語(yǔ)句(不帶 from
子句)會(huì )分兩步執行:
查找一個(gè)模塊,如果有必要還會(huì )加載并初始化模塊。
在局部命名空間中為
import
語(yǔ)句發(fā)生位置所處的作用域定義一個(gè)或多個(gè)名稱(chēng)。
當語(yǔ)句包含多個(gè)子句(由逗號分隔)時(shí)這兩個(gè)步驟將對每個(gè)子句分別執行,如同這些子句被分成獨立的 import 語(yǔ)句一樣。
第一個(gè)步驟即查找和加載模塊的詳情 導入系統 一節中有更詳細的描述,其中也描述了可被導入的多種類(lèi)型的包和模塊,以及可用于定制導入系統的所有鉤子對象。 請注意這一步如果失敗,則可能說(shuō)明模塊無(wú)法找到,或者 是在初始化模塊,包括執行模塊代碼期間發(fā)生了錯誤。
如果成功獲取到請求的模塊,則可以通過(guò)以下三種方式一之在局部命名空間中使用它:
模塊名后使用
as
時(shí),直接把as
后的名稱(chēng)與導入模塊綁定。如果沒(méi)有指定其他名稱(chēng),且被導入的模塊為最高層級模塊,則模塊的名稱(chēng)將被綁定到局部命名空間作為對所導入模塊的引用。
如果被導入的模塊 不是 最高層級模塊,則包含該模塊的最高層級包的名稱(chēng)將被綁定到局部命名空間作為對該最高層級包的引用。 所導入的模塊必須使用其完整限定名稱(chēng)來(lái)訪(fǎng)問(wèn)而不能直接訪(fǎng)問(wèn)。
from
形式使用的過(guò)程略微繁復一些:
查找
from
子句中指定的模塊,如有必要還會(huì )加載并初始化模塊;對于
import
子句中指定的每個(gè)標識符:檢查被導入模塊是否有該名稱(chēng)的屬性
如果沒(méi)有,嘗試導入具有該名稱(chēng)的子模塊,然后再次檢查被導入模塊是否有該屬性
如果未找到該屬性,則引發(fā)
ImportError
。否則的話(huà),將對該值的引用存入局部命名空間,如果有
as
子句則使用其指定的名稱(chēng),否則使用該屬性的名稱(chēng)
示例:
import foo # foo imported and bound locally
import foo.bar.baz # foo, foo.bar, and foo.bar.baz imported, foo bound locally
import foo.bar.baz as fbb # foo, foo.bar, and foo.bar.baz imported, foo.bar.baz bound as fbb
from foo.bar import baz # foo, foo.bar, and foo.bar.baz imported, foo.bar.baz bound as baz
from foo import attr # foo imported and foo.attr bound as attr
如果標識符列表改為一個(gè)星號 ('*'
),則在模塊中定義的全部公有名稱(chēng)都將按 import
語(yǔ)句所在的作用域被綁定到局部命名空間。
一個(gè)模塊所定義的 公有名稱(chēng) 是由在模塊的命名空間中檢測一個(gè)名為 __all__
的變量來(lái)確定的;如果有定義,它必須是一個(gè)字符串列表,其中的項為該模塊所定義或導入的名稱(chēng)。 在 __all__
中所給出的名稱(chēng)都會(huì )被視為公有并且應當存在。 如果 __all__
沒(méi)有被定義,則公有名稱(chēng)的集合將包含在模塊的命名空間中找到的所有不以下劃線(xiàn)字符 ('_'
) 打頭的名稱(chēng)。 __all__
應當包括整個(gè)公有 API。 它的目標是避免意外地導出不屬于 API 的一部分的項(例如在模塊內部被導入和使用的庫模塊)。
通配符形式的導入 --- from module import *
--- 僅在模塊層級上被允許。 嘗試在類(lèi)或函數定義中使用它將引發(fā) SyntaxError
。
當指定要導入哪個(gè)模塊時(shí),你不必指定模塊的絕對名稱(chēng)。 當一個(gè)模塊或包被包含在另一個(gè)包之中時(shí),可以在同一個(gè)最高層級包中進(jìn)行相對導入,而不必提及包名稱(chēng)。 通過(guò)在 from
之后指定的模塊或包中使用前綴點(diǎn)號,你可以在不指定確切名稱(chēng)的情況下指明在當前包層級結構中要上溯多少級。 一個(gè)前綴點(diǎn)號表示是執行導入的模塊所在的當前包,兩個(gè)點(diǎn)號表示上溯一個(gè)包層級。 三個(gè)點(diǎn)號表示上溯兩級,依此類(lèi)推。 因此如果你執行 from . import mod
時(shí)所處位置為 pkg
包內的一個(gè)模塊,則最終你將導入 pkg.mod
。 如果你執行 from ..subpkg2 import mod
時(shí)所處位置為 pkg.subpkg1
則你將導入 pkg.subpkg2.mod
。 有關(guān)相對導入的規范說(shuō)明包含在 包相對導入 一節中。
importlib.import_module()
被提供用來(lái)為動(dòng)態(tài)地確定要導入模塊的應用提供支持。
引發(fā)一個(gè) 審計事件 import
附帶參數 module
, filename
, sys.path
, sys.meta_path
, sys.path_hooks
。
7.11.1. future 語(yǔ)句?
future 語(yǔ)句 是一種針對編譯器的指令,指明某個(gè)特定模塊應當使用在特定的未來(lái)某個(gè) Python 發(fā)行版中成為標準特性的語(yǔ)法或語(yǔ)義。
future 語(yǔ)句的目的是使得向在語(yǔ)言中引入了不兼容改變的 Python 未來(lái)版本的遷移更為容易。 它允許基于每個(gè)模塊在某種新特性成為標準之前的發(fā)行版中使用該特性。
future_stmt ::= "from" "__future__" "import"feature
["as"identifier
] (","feature
["as"identifier
])* | "from" "__future__" "import" "("feature
["as"identifier
] (","feature
["as"identifier
])* [","] ")" feature ::=identifier
future 語(yǔ)句必須在靠近模塊開(kāi)頭的位置出現。 可以出現在 future 語(yǔ)句之前行只有:
模塊的文檔字符串(如果存在),
注釋?zhuān)?/p>
空行,以及
其他 future 語(yǔ)句。
唯一需要使用 future 語(yǔ)句的特性是 標注
(參見(jiàn) PEP 563)。
future 語(yǔ)句所啟用的所有歷史特性仍然為 Python 3 所認可。 其中包括 absolute_import
, division
, generators
, generator_stop
, unicode_literals
, print_function
, nested_scopes
和 with_statement
。 它們都已成為冗余項,因為它們總是為已啟用狀態(tài),保留它們只是為了向后兼容。
future 語(yǔ)句在編譯時(shí)會(huì )被識別并做特殊對待:對核心構造語(yǔ)義的改變常常是通過(guò)生成不同的代碼來(lái)實(shí)現。 新的特性甚至可能會(huì )引入新的不兼容語(yǔ)法(例如新的保留字),在這種情況下編譯器可能需要以不同的方式來(lái)解析模塊。 這樣的決定不能推遲到運行時(shí)方才作出。
對于任何給定的發(fā)布版本,編譯器要知道哪些特性名稱(chēng)已被定義,如果某個(gè) future 語(yǔ)句包含未知的特性則會(huì )引發(fā)編譯時(shí)錯誤。
直接運行時(shí)的語(yǔ)義與任何 import 語(yǔ)句相同:存在一個(gè)后文將詳細說(shuō)明的標準模塊 __future__
,它會(huì )在執行 future 語(yǔ)句時(shí)以通常的方式被導入。
相應的運行時(shí)語(yǔ)義取決于 future 語(yǔ)句所啟用的指定特性。
請注意以下語(yǔ)句沒(méi)有任何特別之處:
import __future__ [as name]
這并非 future 語(yǔ)句;它只是一條沒(méi)有特殊語(yǔ)義或語(yǔ)法限制的普通 import 語(yǔ)句。
在默認情況下,通過(guò)對Code compiled by calls to the 內置函數 exec()
和 compile()
的調用所編譯的代碼如果出現于一個(gè)包含有 future 語(yǔ)句的模塊 M
之中,就會(huì )使用 future 語(yǔ)句所關(guān)聯(lián)的語(yǔ)法和語(yǔ)義。 此行為可以通過(guò) compile()
的可選參數加以控制 --- 請參閱該函數的文檔以了解詳情。
在交互式解釋器提示符中鍵入的 future 語(yǔ)句將在解釋器會(huì )話(huà)此后的交互中有效。 如果一個(gè)解釋器的啟動(dòng)使用了 -i
選項啟動(dòng),并傳入了一個(gè)腳本名稱(chēng)來(lái)執行,且該腳本包含 future 語(yǔ)句,它將在交互式會(huì )話(huà)開(kāi)始執行腳本之后保持有效。
參見(jiàn)
- PEP 236 - 回到 __future__
有關(guān) __future__ 機制的最初提議。
7.12. global
語(yǔ)句?
global_stmt ::= "global"identifier
(","identifier
)*
global
語(yǔ)句是作用于整個(gè)當前代碼塊的聲明。 它意味著(zhù)所列出的標識符將被解讀為全局變量。 要給全局變量賦值不可能不用到 global
關(guān)鍵字,不過(guò)自由變量也可以指向全局變量而不必聲明為全局變量。
在 global
語(yǔ)句中列出的名稱(chēng)不得在同一代碼塊內該 global
語(yǔ)句之前的位置中使用。
在 global
語(yǔ)句中列出的名稱(chēng)不能被定義為形式參數,也不能被作為 with
語(yǔ)句或 except
子句的目標,以及 for
循環(huán)的目標列表、class
定義、函數定義、import
語(yǔ)句或變量標注等等。
CPython implementation detail: 當前的實(shí)現并未強制要求所有的上述限制,但程序不應當濫用這樣的自由,因為未來(lái)的實(shí)現可能會(huì )改為強制要求,并靜默地改變程序的含義。
程序員注意事項: global
是對解析器的指令。 它僅對與 global
語(yǔ)句同時(shí)被解析的代碼起作用。 特別地,包含在提供給內置 exec()
函數字符串或代碼對象中的 global
語(yǔ)句并不會(huì )影響 包含 該函數調用的代碼塊,而包含在這種字符串中的代碼也不會(huì )受到包含該函數調用的代碼中的 global
語(yǔ)句影響。 這同樣適用于 eval()
和 compile()
函數。
7.13. nonlocal
語(yǔ)句?
nonlocal_stmt ::= "nonlocal"identifier
(","identifier
)*
nonlocal
語(yǔ)句會(huì )使得所列出的名稱(chēng)指向之前在最近的包含作用域中綁定的除全局變量以外的變量。 這種功能很重要,因為綁定的默認行為是先搜索局部命名空間。 這個(gè)語(yǔ)句允許被封裝的代碼重新綁定局部作用域以外且非全局(模塊)作用域當中的變量。
與 global
語(yǔ)句中列出的名稱(chēng)不同,nonlocal
語(yǔ)句中列出的名稱(chēng)必須指向之前存在于包含作用域之中的綁定(在這個(gè)應當用來(lái)創(chuàng )建新綁定的作用域不能被無(wú)歧義地確定)。
nonlocal
語(yǔ)句中列出的名稱(chēng)不得與之前存在于局部作用域中的綁定相沖突。