通讀了Python官網的語法說明文檔。原文來自:Python 語言參考(3.8.2版本)。在此,將原文的要點進行記錄與分享。
1 概述
2 詞法分析
Python 程序由一個解析器讀取。輸入到解析器的是一個由詞法分析器所生成的形符流。Python 會將讀取的程序文本轉為 Unicode 碼點;源文件的文本編碼可由編碼聲明指定,默認為 UTF-8。
2.1 行結構
-
邏輯行以
NEWLINE
形符表示。- 語句不能跨邏輯行。
- 邏輯行可由多個物理行按規則拼接
- 物理行以換行字符終止,如LF,CR LF,CR等
2.2 其它形符
2.3 標識符和關鍵字
Python關鍵字
False await else import pass
None break except in raise
True class finally is return
and continue for lambda try
as def from nonlocal while
assert del global not with
async elif if or yield
特殊的標識符
-
_*
:以下劃線字符_
開始的標識符不會被import語句from module import *
導入。 -
__*__
:以雙下劃線字符開始并結尾的標識符為系統定義的名稱,特殊方法對于的名稱 -
__*
:以雙下劃線開始的標識符是類的私有名稱,會被類定義隱式的轉換。
2.4 字面值
字面值直接表示一些內置類型的常量
- 字符串、字節串字面值
- 格式化字符串字面值
- 數字字面值:整數、浮點數、虛數
格式化字符串字面值
以'f'
或'F'
前綴開始的字符串為格式化字符串。其中以花括號{}
標識的是可替換字段。
f_string ::= (literal_char | "{{" | "}}" | replacement_field)*
replacement_field ::= "{" f_expression ["!" conversion] [":" format_spec] "}"
f_expression ::= (conditional_expression | "*" or_expr)
("," conditional_expression | "," "*" or_expr)* [","]
| yield_expression
conversion ::= "s" | "r" | "a"
format_spec ::= (literal_char | NULL | replacement_field)*
literal_char ::= <any code point except "{", "}" or NULL>
注:
-
! conversion
轉換符,表達式f_expression
將先轉換在格式化:-
!s
:以str()
轉換 -
!r
:以repr()
轉換 -
!a
:以ascii()
轉換
-
2.5 運算符
2.6 分隔符
3 數據模型
3.1 對象、值與類型
每個對象有各自的編號、類型和值。編號:id()
函數返回代表編號的整數值,在CPython中即為內存地址,編號是不可變的。類型:type()
返回對象的類型,類型也是不可變的。值:有些對象的值是是否可變分為可變的(mutable)與不可變的(immutable)。對象的可變性是由類型決定的。
注:當不可變容器包含可變對象的引用時,后者的數值改變也造成容器數值的改變。不過,容器包含的內容未變,所以依然稱該容器是不可變的。也就是說,不可變并非是值不改變。
對象絕不會顯示被銷毀,當無法訪問時被垃圾回收。一些對象包含對外部資源的引用,當對象被垃圾回收時這些資源得到釋放。未明確的釋放外部資源,這些對象通常有close()
方法,在程序中以try...finally
語句和with
語句提供的操作更便捷。
3.2 標準類型層級
None
NotImplemented
邏輯值為真Ellipsis
邏輯值為真-
numbers.Number
- numbers.Integeral
- 整形(int)
- 布爾型(bool)
- numbers.Real(float)
- numbers.Complex(complex)
- numbers.Integeral
-
序列: 有限有序集,支持
len()
,切片a[i:j]
,擴展切片a[i:j:k]
- 不可變序列:
- 字符串
str
- 元組
- 字節串
bytes
- 字符串
- 可變序列:
- 列表
- 字節數值
bytearray
- 擴展模塊
array
與collections
- 不可變序列:
-
集合類型:無序有限集,支持迭代,支持
len()
- 集合
set()
- 凍結集合
frozenset()
- 集合
-
映射:任意索引類型的有限集合,支持下標
a[k]
用于賦值或del
語句,支持len()
- 字典
-
可調用類型
-
用戶定義函數,特殊屬性:
-
__doc__
可寫 -
__name__
可寫 -
__qualname__
可寫,函數限定名稱,顯式從模塊開始的層級 -
__module__
可寫,函數所述模塊的名稱 -
__defaults__
可寫,默認參數值構成的元組 -
__code__
可寫,變異后的函數體代碼 -
__globals__
只讀,函數所屬模塊的全局命名空間字典引用 -
__dict__
可寫,命名空間支持的函數屬性 -
__closure__
只讀 -
__annotations__
可寫,包含參數標注的自定 -
__kwdefaults__
可寫,僅包含關鍵字參數默認值的字典
-
-
實例方法,結合類、類實例與可調對象。
- 特殊只讀屬性:
__self__
為類實例,__func__
為函數對象,__doc__
為方法文檔(即__func__.__doc__
)__name__
即__func__.__name__
,__module__
方法所在模塊名稱。 - 注:實例方法的
__self__
參數指代實例對象; 類方法的__self__
參數指代類型。 - 注:從函數對象到實例方法的轉換在每一次實例獲取方法時發生,一種優化方法時將實例方法屬性在本地保存,每次使用時調用本地對象。
- 特殊只讀屬性:
生成器函數:使用
yield
語句的函數/方法。函數被調用時返回迭代器對象。協程函數: 使用
async def
定義的函數/方法。異步生成器函數:使用
async def
定義的含有yeild
語句的函數/方法。-
內置函數:對于C函數的外部封裝。
- 特殊只讀屬性:
__doc__
,__name__
,__self__
為None
,__module__
,
- 特殊只讀屬性:
內置方法:相比內置函數,多了一個傳入C函數的對象作為隱式的額外參數
__self__
。類:
__new__()
,__init__()
類實例:定義
__call__()
使類實例可調
-
-
模塊
- 具有字典對象實現的命名空間,也是模塊中函數
__globals__
所引用的字典 - 可寫屬性:
__name__
,__doc__
,__annotations__
,__file__
- 只讀屬性
__dict__
- 具有字典對象實現的命名空間,也是模塊中函數
-
自定義類
- 每個類都通過字典實現獨立的命名空間,類屬性在字典中查找
- 特別屬性:
__name__
,__module__
類所在模塊,__dict__
,__bases__
包含基類的元組,__doc__
,__annotations__
-
類實例
- 通過調用類對象創建,每個類實例通過字典實現獨立的命名空間。
- 若為找到類屬性,而對象對應的類具有
__getattr__()
方法則會調用該方法。 - 屬性賦值與刪除會更新實例字典,但不更新類字典。若類具有
__setattr__()
與__delattr()__
則調用方法而不直接更新實例字典 - 特殊屬性:
__dict__
,__class__
I/0對象
-
內部類型(定義可能在未來解釋器版本中變化)
- 代碼對象
- 編譯為字節的可執行Python代碼,或稱
bytecode
- vs函數對象,函數對象具有全局對象的引用,代碼對象不包含上下文
- 編譯為字節的可執行Python代碼,或稱
- 幀對象:表示執行幀
- 回溯對象:表示異常的棧跟蹤記錄。
- 切片對象:表示
__getitem__()
方法得到的切片, - 靜態方法對象:
- 為對任意其它對象的封裝,靜態方法對象自身是不可調用的。
- 從類或類實例中獲得的靜態方法對象時,獲得的是被封裝的對象。
- 可由
staticmethod()
構造器創建
- 類方法對象:
- 對其他對象的封裝。
- 可由
classmethod()
構造器創建。
- 代碼對象
3.3 特殊方法
3.3.1 基本定制Basic customization
-
object.__new__(cls[,...])
- 創建cls類的新實例,
__new__()
總是一個靜態方法。返回值應為新對象(通常為cls)實例 - 典型的實現總有
super().__new__(cls[, ...])
調用。 - 如果
__new__()
發返回了一個cls的實例或者子類,則新實例將調用__init__(self[, ...])
進行初始化 - 若
__new__()
沒有返回cls的實例,則不會有__init__()
調用 - 用以對int,str或tuple等子類的自定義;用以創建唯一對象singleton
- 創建cls類的新實例,
-
object.__init__(self[, ...])
- 其參數與傳遞給構造表達器的參數相同。
- 應確保基類正確初始化
super().__init__([args...])
- 返回值為
None
-
object.__del__(self)
- 在實例被銷毀時調用
- 派生類需確保基類的
__del__()
正確被調用 - 注:
del x
將x
的引用計數減一;當引用計數為零時,才可能執行x.__del__()
-
object.__repr__(self)
:- 若可能,使用輸出的字符串能重建相同取值的對象;若不可能則返回形如
<...一些有用信息...>
的字符串
- 若可能,使用輸出的字符串能重建相同取值的對象;若不可能則返回形如
-
object.__str__(self)
:一種非正式或格式良好的字符串 -
object.__bytes__(self)
:返回bytes
對象 -
object.__format__(self, format_spec)
:對象的格式化字符串顯示 - 比較方法
object.__lt__(self, other)
object.__le__(self, other)
object.__eq__(self, other)
object.__ne__(self, other)
object.__gt__(self, other)
object.__ge__(self, other)
- 注:當比較操作的左操作數未實現相關函數,而右操作數有實現,則調用右操作數的方法;當右操作數是左操作數的子類時,優先有操作數的方法
-
object.__hash__(self)
- 用于對哈希集
set
,frozenset
,dict
執行哈希函數hash()
。建議將參與比較的對象組件打包為元組整體進行hash計算 - 與
__eq__()
- 用戶定義類默認有
__eq__()
與__hash__()
方法,確保當x==y
時意味著x is y
且hash(x)==hash(y)
- 若僅定義
__eq__()
時,則將__hash__()
隱式設置為None
;若須保留父類的__hash__()
實現,須在類中明確__hash__ = <ParentClass>.__hash__
- 若未定義
__eq__()
則不應定義__hash__()
;若定義__eq__()
同時定義了可變對象也不應定義__hash__()
,否則對象可能至于錯誤的哈希桶中。 - 若未定義
__eq__()
時也不需要默認的__hash__()
,則應在類中明確__hash__ = None
- 用戶定義類默認有
- 注: 在str與bytes對象的hash值由隨機數加鹽,在單獨的python進程中是一致的。
- 用于對哈希集
-
object.__bool__(self)
- 若類未定義
__bool__()
也未定義__len__()
則實例邏輯值為真
- 若類未定義
3.3.2 屬性訪問
-
object.__getattr__(self, name)
- 當默認屬性訪問失敗時調用:
- 可能由于
__getattribute__()
時 ,name
非實例屬性 - 或者對于
name
特性調用__get__()
時
- 可能由于
- 當默認屬性訪問失敗時調用:
-
object.__getattribute__(self, name)
- 類實例屬性訪問調用。為避免方法的無限遞歸,總是調用相同名稱的基類方法實現
-
object.__setattr__(self, name, value)
- 當實例屬性被賦值時調用。正常實現是調用相同名稱的基類方法
-
object.__delattr__(self, name)
- 與
__setattr__()
效果范圍類似,僅在del obj.name
時生效
- 與
-
object.__dir__(self)
- 對象調用
dir()
時調用,返回值為一個序列,
- 對象調用
3.3.2.1 自定義模塊屬性訪問
特殊名稱__getattr_
與__dir__
可用來自定義對模塊屬性的訪問
自定義模塊的行為,可以將模塊對象的__class__
屬性設置為types.ModuleType
的子類:
sys.modules[__name__].__class__ = ***Module
3.3.2.2 實現描述器
當含有如下__get__
,__set__
,__delete__
,__set_name__
特殊方法的類(稱為描述器descriptor)的實例是其他所有類的成員時,這些特殊方法才有效
-
object.__get__(self,instance,owner=None)
- 實現所有者類屬性/類實例屬性的方法
-
object.__set__(self,instance,value)
- 設置instance指向的屬性值為新值
- 使用
__set__()
或__delete__()
將描述器變為數據描述器
object.__delete__(self,instance)
-
object.__set_name__(self,owner,name)
- 在所有者創建是被調用,描述器賦值給name
3.3.2.3 調用描述器
描述器就是具有綁定行為的對象屬性,屬性方位被描述器的方法重載。
若沒有定義__get__()
,屬性訪問將返回描述器自身
若定義了__set__()
/__delele__()
則為數據描述器,否則為非數據描述器;通常數據描述器定義__get__()
與__set__()
而非數據描述器僅定義__get__()
方法。數據描述器總是重載字典中實例定義。而非數據描述器可以被實例重載。
Python方法(包括staticmethod()
和 classmethod()
) 都是作為非描述器來實現的。因此實例可以重定義并重載方法。這允許單個實例獲得與相同類的其他實例不一樣的行為。
property()
函數是作為數據描述器來實現的。因此實例不能重載特性屬性的行為。
3.3.2.4 __slots__
-
object.__slots__
-
slots用以顯示聲明數據成員,禁止創建
__dict__
以及__weakref__
除非顯示聲明或在父類中可用. - 繼承一個未定義slots的類時,實例的
__dict__
與__weakref__
總是可訪問的。
-
slots用以顯示聲明數據成員,禁止創建
3.3.3 類創建
classmethod object.__init_subclass__(cls)
- 當一個類繼承自其它類時,基類的init_subclass會被調用。
- 基類控制子類的特性,相較于元類更加靈活
- 隱式的
classmethod
元類
默認情況,類是由type()
構建type(name,bases,dict)
。在類創建定義中傳入metaclass
關鍵字參數,控制類創建使用的元類。
- 解析MRO條目
- 確定適當的元類
- 若沒有基類且沒有顯示指定元類,使用
type()
- 若給出顯示的元類且不是
type()
的實例,則直接用作元類 - 若給出一個
type()
實例作為元類,或者定義了基類,則使用最近派生的元類
- 若沒有基類且沒有顯示指定元類,使用
- 準備類命名空間
- 若元類有
__prepare__
屬性,則以namespace = metaclass.__prepare__(name,bases,**kwds)
調用,namespace
傳遞給元類的__new__
- 元類的
__prepare__
須顯式聲明為classmethod -
__prepare__
返回的命名空間返回給__new__
,但最終類對象創建時,命名空間拷貝至新的只讀代理dict中,作為類對象的字典。
- 若元類有
- 執行類主體
- 創建類對象
- 執行元類
__new__
與__init__
- 執行元類
3.3.4 實例與子類檢查
用以重載isinstance()
與issubclass()
內置函數行為,這樣可以通過元類實現抽象基類ABC功能:
-class.__instancecheck__(self, instance)
class.__subclasscheck__(self, instance)
3.3.5 模擬泛型類型
classmethod object.__class_getitem_(cls, key)
。按照key參數指定的類型返回一個表示泛型類的專門化對象
3.3.6 模擬可調多項
object.__call__(self[, args...])
3.3.7 模擬容器類型
可以定義下列方法來實現容器對象。 容器通常屬于序列(如列表或元組)或映射(如字典),但也存在其他形式的容器。 前幾個方法集被用于模擬序列或是模擬映射;兩者的不同之處在于序列允許的鍵應為整數 k 且 0 <= k < N 其中 N 是序列或定義指定區間的項的切片對象的長度。 此外還建議讓映射提供 keys(), values(), items(), get(), clear(), setdefault(), pop(), popitem(), copy() 以及 update() 等方法,它們的行為應與 Python 標準字典對象的相應方法類似。 此外 collections.abc 模塊提供了一個 MutableMapping 抽象基類以便根據由 getitem(), setitem(), delitem(), 和 keys() 組成的基本集來創建所需的方法。 可變序列還應像 Python 標準列表對象那樣提供 append(), count(), index(), extend(), insert(), pop(), remove(), reverse() 和 sort() 等方法。 最后,序列類型還應通過定義下文描述的 add(), radd(), iadd(), mul(), rmul() 和 imul() 等方法來實現加法(指拼接)和乘法(指重復);它們不應定義其他數值運算符。 此外還建議映射和序列都實現 contains() 方法以允許高效地使用 in 運算符;對于映射,in 應該搜索映射的鍵;對于序列,則應搜索其中的值。 另外還建議映射和序列都實現 iter() 方法以允許高效地迭代容器中的條目;對于映射,iter() 應當迭代對象的鍵;對于序列,則應當迭代其中的值
object.__len__(self)
-
object.__length_hint__(self)
(可選) object.__getitem__(self,key)
object.__setitem__(self,key,value)
object.__delitem__(self,key)
-
object.__missing__(self,key)
(在getitem找不到鍵時調用) object.__iter__(self)
object.__reversed__(self)
object.__contains__(self,item)
3.3.8 模擬數字類型
運算 | 基本 | 反射 | 擴展 | |
---|---|---|---|---|
+ |
__add__ |
__radd__ |
__iadd__ |
|
- |
__sub__ |
|||
* |
__mul__ |
|||
@ |
__matmul__ |
|||
/ |
__truediv__ |
|||
// |
__floordiv__ |
|||
% |
__mod__ |
|||
divmod() |
__divmod__ |
None | ||
pow() /**
|
__pow__ |
|||
<< |
__lshift__ |
|||
>> |
__rshift__ |
|||
& |
__and__ |
|||
^ |
__xor__ |
|||
` | ` | __or__ |
-
__neg__
,__pos__
,__abs__
(abs()
),__invert__
(~
) -
__complex__
,__int__
,__float__
__index__
-
__round__
,__trunc__
,__floor__
,__ceil__
3.3.9 with語句上下文管理器
上下文管理器是指執行with
語句時需要建立的實時上下文。上下文管理器負責處理進入、退出實時上下文時需要執行的代碼塊。通常使用with
語句,也可以直接調用
-
object.__enter__(self)
進入上下文。 -
object.__exit__(self,exc_type, exc_value, traceback)
退出上下文,三個參數描述了導致上下文退出時的異常;若上下文正常退出,三個參數均為None
3.4 協程Coroutines
3.4.1 可等待對象Awaitable Objects
awaitable
對象實現__await__()
方法,在await
語句中使用。從async def
函數返回的Coroutine
對象也屬于可等待對象。
object.__await__(self)
必須返回一個iterator
3.4.2 協程對象Coroutine Objects
Coroutine
對象屬于可等待對象。 協程的執行可通過調用__await__()
并迭代其結果來進行控制。當協程結束執行并返回時,迭代器會引發StopIteration
,該異常的value屬性將指向返回值。
協程也具有下面列出的方法,它們類似于生成器的對應方法。但是,與生成器不同,協程并不直接支持迭代。
-
coroutine.send(value)
開始或恢復協程的執行. -
coroutine.throw(type[,value[,traceback]])
在協程內引發指定的異常。 -
coroutine.close()
此方法會使得協程清理自身并退出
3.4.3 異步迭代器Asynchronous Iterators
異步迭代器可以在__anext__
方法中調用異步代碼。
-
object.__aiter__(self)
返回一個異步迭代器對象 -
object.__anext__(self)
返回一個可等待對象的下一個結果值,或StopAsyncIteration
3.4.4 異步上下文管理器
異步上下文管理器可在async with
語句中使用,需要定義__aenter__
和__aexit__
方法。
4 執行模型
4.1 程序結構
代碼塊被作為一個單元來執行:模塊、函數體、類定義。內置函數eval()
與exec()
的字符串參數也是代碼塊。
代碼塊在執行幀中被執行,一個幀包含某些管理信息并決定代碼塊執行后將如何繼續執行。
4.2 命名與綁定
4.2.1 名稱綁定
-
名稱用于指代對象,通過綁定操作引入:函數的形參,
import
語句,類與函數定義名稱,被表達式賦值的目標,for
循環開始,with
與except
語句的as
后。 -
import語句
from ... import *
將模塊定義的所有導入模塊綁定,這種形式綁定僅可用于模塊層級。 -
del
語句的目標是解除目標綁定。 - 每條賦值語句或導入語句均發生在類/函數內部定義的代碼塊中,或者在模塊層級(最高層級的代碼塊)
- 名稱綁定在代碼塊中,則為代碼塊的局部變量,除非聲明
nonlocal
或global
。若名稱綁定在模塊層級,則為全局變量。(模塊代碼塊的變量即為局部變量又為全局變量。)如果變量在一個代碼塊中使用但是沒有定義,則為自由變量
4.2.2 名稱的解析
- 作用域定義了代碼塊中名稱的可見性。如果代碼塊定義局部變量,其作用域包括該代碼塊。內部代碼塊會屏蔽外部代碼塊的相同名稱綁定。
- 環境指對一個代碼塊可見的所有作用域的集合。當一個名稱在代碼塊中使用時,由它最近的作用域解析。
- 一個代碼塊內任何位置的名稱綁定導致整個代碼塊對該名稱的引用均在此代碼塊內。
-
global
語句在代碼塊中表示,所有對該語句指定名稱的使用都是最高層級命名空間對該名稱的綁定引用。最高層級命名空間就是全局命名空間,包含:模塊命名空間、內置命名空間。global
語句必須位于所有指定名稱使用之前 -
nonlocal
語句使名稱指向之前的最近包含函數作用域中的綁定變量 - 模塊的作用域在模塊第一次被導入時自動創建,一個腳本的主模塊總是被命名為
__main__
- 類定義代碼塊以及
exec()
與eval()
參數的名稱解析是特殊情況。未綁定的局部變量會在全局命名空間查找。?類代碼塊定義的名稱的作用域限制在類代碼塊中,不會擴展到方法(包括推導式與生成器表達式)中。
4.2.3 內置命名空間與受限的執行
與代碼塊執行相關的內置命名空間是通過全局命名空間中的builtins來找到。在__main__
模塊中,builtins就是內置模塊builtins
;在其它模塊中builtins是builtins
模塊字典的別名
4.2.4 與動態特性的交互
eval()
與exec()
函數沒有對完整環境的訪問權限以解析名稱。名稱可以在調用者的局部或者全局命名空間被解析。自由變量的解析不是在最近包含的命名空間,而是在全局命名空間中。
4.3 異常
pass
5 導入系統
import
語句是發起導入機制的常用方式。importlib.import_module()
以及__import__()
等函數也可以用來發起調用導入機制。
import
語句完成兩個操作:搜索指定名稱的模塊,然后將搜索結果綁定至當前作用域名稱。搜索操作為__import__()
函數調用,函數的返回值用于執行綁定操作。
對__import__()
的直接調用將僅執行模塊搜索以及在找到時的模塊創建操作,但可能產生一些副作用,例如導入父包以及更新緩存。
當一個模塊首次被導入時,Python會搜索該模塊,如果未找到就創建一個module對象并初始化它。
5.1 importlib
importlib
模塊用來與導入系統進行交互。例如importlib.import_module()
提供了比內置import()更推薦的調用導入機制接口
5.2 包
包相當于將模塊組織在一起的目錄,任何具有path屬性的模塊都看作是包。
- 常規包:含有
__init__.py
文件的目錄。當常規包被導入時,該__init__.py
文件被隱式執行。 - 命名空間包:由多個部分組成,每個部分為父包增加子包,沒有
__init__.py
文件。
5.3 搜索
Python根據導入模塊的完整限定名稱開始所示。一個指向子模塊的帶點號路徑將從父包開始依次導入。
- 模塊緩存:
-
sys.modules
緩存之前所有導入的模塊。 -
sys.modules
鍵值對應的值為需要導入的模塊。刪除鍵值會是模塊緩存的條目無效。
-
- 查找器:
- 查找器的任務是確定是否能使用其所知的策略找到該名稱的模塊。
- Python包含多個默認的查找器:第一個負責定位內置模塊;第二個負責定位凍結模塊;第三個負載在import path(通常來自
sys.path
,子包還包含上級包__path__
)中搜索模塊。 - 查找器返回一個模塊的模塊規格說明(module spec),以供后續加載過程使用
- 導入鉤子(Import hooks):
- 實現導入機制的可擴展性,包含兩種鉤子:元鉤子(meta hooks)與導入路徑鉤子(import path hooks)
-
元鉤子導入開始時被調用(除
sys.modules
緩存查找外,其它導入過程尚未發生)。能夠重載查找器特性。元鉤子注冊通過向sys.meta_path
添加查找器對象完成。(元鉤子包含三個默認查找器BuiltinImporter,FrozenImporter,PathFinder實現上述Python默認查找器功能) -
導入路徑鉤子在遇到所關聯的路徑條目時被調用。通過向
sys.path_hooks
添加可調用對象完成。(通常被PathFinder在查找時使用)
- 元路徑查找器:
- 在
sys.modules
找不到模塊時,Python接著搜索sys.meta_path
元路徑查找器。元路徑查找器必須實現find_spec()
方法。 - 若
sys.meta_path
處理過程到達列表末尾仍未返回說明,則放棄導入過程。
- 在
5.4 加載
在加載器執行模塊代碼前,先將模塊增加至sys.modules
中。模塊加載委托加載器執行exec_module()
或load_modules()
進行。
-
子模塊:當導入
spam.foo
之后,在spam
中將有一個子模塊foo
的屬性。 - 模塊規格說明:作為模塊對象的
__spec__
屬性對外公開(參見importlib) - 模塊屬性:
- 導入機制在加載期間根據模塊規格說明填充以下屬性,在加載器執行模塊前完成
-
__name__
完整限定名稱,在導入系統中唯一標識模塊 -
__loader__
加載器 -
__package__
可以與name取值相同,對于子模塊應設為父包名 __spec__
-
__path__
模塊為包是必須設置,必須有字符串組成的可迭代對象,于子包導入期間使用。 -
__file__
可選屬性,文件位置 -
__cached__
可選屬性,編譯緩存文件位置
- 模塊的repr
- 緩存字節碼:使用
--check-hash-based-pycs
開啟基于哈希的.pyc文件有效性檢查。
5.5 基于路徑的查找器
元路徑查找器之一是基于路徑的查找器(path based finder)PathFinder
,用以搜索import path
。基于路徑的查找器只是遍歷路徑,具體的查找使用路徑條目查找器(path entry finder)進行,并產生緩存查找器對象sys.path_importer_cache
以避免重復的費時查找。
如果路徑條目不在緩存中,基于路徑的查找器將在每個條目上迭代sys.path_hooks的可調用對象,若找到模塊,則返回路徑條目查找器對象。
5.6 替換標準導入系統
5.7 包相對導入
導入時使用前綴點號,一個前綴點號表示相對當前包,額外每一個點號代表向上一級
- 絕對導入可以使用
import ...
或from ... import ...
語法 - 相對導入只能使用
from ... import ...
語法形式
5.8 關于__main__
__main__
模塊在解釋器啟動時直接初始化。__main__.__spec__
屬性為None
。當在此導入時,__spec__
為模塊規格說明
6 表達式
6.1 算術轉換
6.2 原子Atom
原子指表達式的最基本構成元素。
atom ::= identifier | literal | enclosure
enclosure ::= parenth_form | list_display | dict_display | set_display
| generator_expression | yield_atom
-
identifier
標識符 -
literal
字面值 -
enclosure
附件
附件包括:
-
parenth_form
帶括號的形式,bystarred_expression
-
comprehesion
推導式,byassignment_expression
-
list_display
列表的顯示,bystarred_list
與comprehension
-
set_display
集合的顯示,bystarred_list
與comprehension
-
dict_display
字典的顯示,byexpression
` -
generator_expression
生成器表達式,byexpression
` -
yield_atom
yield表達式,byexpression_list
與expression
6.2.1 標識符identifier
6.2.2 字面值literal
literal ::= stringliteral | bytesliteral
| integer | floatnumber | imagnumber
6.2.3 帶括號的形式parenth_form
parenth_form ::= "(" [starred_expression] ")"
6.2.4 推導式comprehension
comprehension ::= assignment_expression/*賦值表達式*/ comp_for
comp_for ::= ["async"] "for" target_list "in" or_test [comp_iter]
comp_iter ::= comp_for | comp_if
comp_if ::= "if" expression_nocond [comp_iter]
Python中,為了構建列表、集合與字典,采用兩種方式:
- 第一種的顯示的列出容器內容,
- 第二種是通過一組循環和篩選指令計算出來,稱為推導式
comp_iter
是推導式結構的隱式作用域。最左側/最外層的for語句在作用域中求職后,作為參數傳入推導式內部的隱式作用域。
6.2.5 列表顯示list_display
list_display ::= "[" [starred_list | comprehension] "]"
# 方括號、括號內可為空
6.2.6 集合顯示set_display
set_display ::= "{" (starred_list | comprehension) "}"
# 花括號、括號內不為空,否則為字典
6.2.7 字典顯示dict_display
dict_display ::= "{" [key_datum_list | dict_comprehension] "}"
key_datum_list ::= key_datum ("," key_datum)* [","]
key_datum ::= expression ":" expression | "**" or_expr
dict_comprehension ::= expression ":" expression comp_for
注:雙星號**表示字典拆包,操作數必須是一個mapping
。
6.2.8 生成器表達式
generator_expression ::= "(" expression comp_for ")"
以圓括號括起來的推導式,將產生一個新的生成器對象。
6.2.9 yield表達式
yield_atom ::= "(" yield_expression ")"
yield_expression ::= "yield" [expression_list | "from" expression]
注:當yield表達式是賦值語句右側的唯一表達式時,括號可以省略
生成器-迭代器Generator-iterator方法:
-
generator.__next__()
- 返回
yield
表達式的expression_list
值
- 返回
-
generator.send(value)
-
value參數為
yield
表達式的結果 - 返回生成器的下一個值
-
value參數為
-
generator.throw(type[,value[,traceback]])
- 在生成器暫停位置印發
type
類型異常
- 在生成器暫停位置印發
-
generator.close()
- 在稱長期函數暫停位置引發
GeneratorExit
- 在稱長期函數暫停位置引發
6.3 原型Primary
primary ::= atom | attributeref | subscription | slicing | call
原型表示編程語言中最緊密的綁定操作。
-
atributeref
屬性引用 -
subscription
下標抽取 -
slicing
切片 -
call
調用
6.3.1 屬性引用
attributeref ::= primary "." identifier
注:此處原型應支持屬性引用,否則將產生AttributeError
6.3.2下標抽取
subscription ::= primary "[" expression_list "]"
抽取是在序列或映射中進行。
注:如果原型為映射,表達式列表必須求值為一個以該映射的鍵為值的對象,值/元組;如果原型為序列,表達式列表必須求值為一個整數或一個切片
6.3.3 切片
slicing ::= primary "[" slice_list "]"
slice_list ::= slice_item ("," slice_item)* [","]
slice_item ::= expression | proper_slice
proper_slice ::= [lower_bound] ":" [upper_bound] [ ":" [stride] ]
lower_bound ::= expression
upper_bound ::= expression
stride ::= expression
注: 如果切片列表包含至少一個逗號,則鍵將是一個包含切片項轉換的元組;否則的話,鍵將是單個切片項的轉換
6.3.4 調用
call ::= primary "(" [argument_list [","] | comprehension] ")"
argument_list ::= positional_arguments ["," starred_and_keywords]
["," keywords_arguments]
| starred_and_keywords ["," keywords_arguments]
| keywords_arguments
positional_arguments ::= positional_item ("," positional_item)*
positional_item ::= assignment_expression | "*" expression
starred_and_keywords ::= ("*" expression | keyword_item)
("," "*" expression | "," keyword_item)*
keywords_arguments ::= (keyword_item | "**" expression)
("," keyword_item | "," "**" expression)*
keyword_item ::= identifier "=" expression
-
poisitional_arguments
位置參數:賦值表達式
or*表達式
-
starred_and_keywords
:混用*表達式
(位置參數)or關鍵字項
(關鍵字參數) -
keyword_item
關鍵字參數:關鍵字項
or**表達式
若存在關鍵字參數,首先為正式參數創建一個未填充的空列表,將所有位置參數從前至后依次填入;然后對于每個關鍵字參數,使用標識符填充相應參數,若空位已被填充則TypeError
;填充完后的空位使用函數的默認值填充,若沒有默認值則TypeError
6.4 await表達式
只能在coroutine function
內部使用
await_expr ::= "await" primary
6.5 冪運算符
power ::= (await_expr | primary) ["**" u_expr]
注:冪運算符的綁定比在其左側的一元運算符更緊密;但綁定緊密程度不及在其右側的一元運算符
6.6 一元算術和位運算
u_expr ::= power | "-" u_expr | "+" u_expr | "~" u_expr
6.7 二元算術運算
m_expr ::= u_expr | m_expr "*" u_expr | m_expr "@" m_expr |
m_expr "http://" u_expr | m_expr "/" u_expr |
m_expr "%" u_expr
a_expr ::= m_expr | a_expr "+" m_expr | a_expr "-" m_expr
6.8 移位運算
shift_expr ::= a_expr | shift_expr ("<<" | ">>") a_expr
6.9 二元位運算
and_expr ::= shift_expr | and_expr "&" shift_expr
xor_expr ::= and_expr | xor_expr "^" and_expr
or_expr ::= xor_expr | or_expr "|" xor_expr
6.10 比較運算
comparison ::= or_expr (comp_operator or_expr)*
comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "!="
| "is" ["not"] | ["not"] "in"
6.11 布爾運算
not_test ::= comparison | "not" not_test
and_test ::= not_test | and_test "and" not_test
or_test ::= and_test | or_test "or" and_test
6.12 賦值表達式
assignment_expression ::= [identifier ":="] expression
注:賦值表達式可用于定義:1)列表、集合與字典中的推導式;2)調用中的位置參數;3)作為列表顯示、集合顯示的表達式列表。
6.13 條件表達式、表達式、lambda表達式
conditional_expression ::= or_test ["if" or_test "else" expression]
注:表達式x if C else y
首先對C求值,結果為真再對x求值,否則對y求值
expression ::= conditional_expression | lambda_expr
lambda_expr ::= "lambda" [parameter_list] ":" expression
expression_nocond ::= or_test | lambda_expr_nocond
lambda_expr_nocond ::= "lambda" [parameter_list] ":" expression_nocond
6.14 lambda表達式
表達式lambda parameters: expression
會產生一個函數對象,該未命名對象類似如下定義
def <lambda>(parameters):
return expression
6.15 表達式列表
expression_list ::= expression ("," expression)* [","]
starred_item ::= assignment_expression | "*" or_expr
starred_expression ::= expression | (starred_item ",")* [starred_item]
starred_list ::= starred_item ("," starred_item)* [","]
注:starred_list
相比較于expression_list
增加了星號表達式* ...
與賦值表達式... := ...
,用于列表顯示、集合顯示表達
6.16 求值順序
6.17 運算符優先級
7 簡單語句
簡單語句由一個單獨的邏輯行構成。 多條簡單語句可以存在于同一行內并以分號分隔
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 表達式語句
expression_stmt ::= starred_expression
7.2 賦值語句
assignment_stmt ::= (target_list "=")+ (starred_expression | yield_expression)
target_list ::= target ("," target)* [","]
target ::= identifier
| "(" [target_list] ")"
| "[" [target_list] "]"
| attributeref
| subscription
| slicing
| "*" target
7.3 assert語句
簡單的assert expression1, expression2
相當于
if __debug__:
if not expression: raise AssertionError(expression2)
7.4 pass語句
7.5 del語句
7.6 return語句
7.7 yeild語句
7.8 raise語句
raise_stmt ::= "raise" [expression ["from" expression]]
如果不帶表達式,raise
將重新引起當前作用域內的最后一個激活的異常,若沒有異常則引發RuntimeError
。
raise
的首個表達式表異常對象,必須是BaseException
子類或實例。from
子句用于異常串聯,若在異常處理器或finally
引發,串聯機制隱式發揮作用,可通過在from
子句中指定None
來顯示抑制
try:
print(1 / 0)
except:
raise RuntimeError("Something bad happened") from None
7.9 break語句
7.10 continue 語句
7.11 import語句
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" module "import" "*"
module ::= (identifier ".")* identifier
relative_module ::= "."* module | "."+
7.12 global語句
7.13 nolocal語句
8 復合語句
復合語句是包含其它語句(語句組)的語句;它們會以某種方式影響或控制所包含其它語句的執行。
-
if
,while
和for
語句用來實現傳統的控制流程構造。 -
try
語句為一組語句指定異常處理和/和清理代碼。 -
with
語句允許在一個代碼塊周圍執行初始化和終結化代碼。 - 函數和類定義在語法上也屬于復合語句。
一條復合語句由一個或多個子句組成。
- 子句頭以一個作為唯一標識的關鍵字開始并以一個冒號結束。
- 子句體是由一個子句控制的一組語句。 子句體可以是在子句頭的冒號之后與其同處一行的一條或由分號分隔的多條簡單語句,或者也可以是在其之后縮進的一行或多行語句。但是,只有在縮進形式下才可以嵌套復合語句。
#復合語句
compound_stmt ::= if_stmt
| while_stmt
| for_stmt
| try_stmt
| with_stmt
| funcdef
| classdef
| async_with_stmt
| async_for_stmt
| async_funcdef
#子句體
suite ::= stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT
statement ::= stmt_list NEWLINE | compound_stmt
stmt_list ::= simple_stmt (";" simple_stmt)* [";"]
8.1 if語句
8.2 while語句
while_stmt ::= "while" assignment_expression ":" suite
["else" ":" suite]
8.3 for語句
for_stmt ::= "for" target_list "in" expression_list ":" suite
["else" ":" suite]
注: 系統將為expression_list
的結果創建一個迭代器,然后將為迭代器所提供的每一項執行一次子句體,具體次序與迭代器的返回順序一致
注:當所有項被耗盡時,else
子句的子句體如果存在將會被執行,并終止循環。
- for循環子句頭會對目標列表的變量進行賦值,將覆蓋變量的賦值(包括循環體內的賦值)
- 目標列表的名稱在循環結束時不會被刪除,但是如果迭代序列為空,名稱將不會被賦值。
8.4 try語句
try_stmt ::= try1_stmt | try2_stmt
try1_stmt ::= "try" ":" suite
("except" [expression ["as" identifier]] ":" suite)+
["else" ":" suite]
["finally" ":" suite]
try2_stmt ::= "try" ":" suite
"finally" ":" suite
- 如果在對
except
子句頭中的表達式求值時引發了異常,則原來對異常處理器的搜索會被取消,啟動對新的異常的搜索 - 當找到一個匹配的
except
子句時,該異常將被賦值給該except
子句在as
關鍵字之后指定的目標,并在except
子句體執行。 - 當使用
as
將目標賦值為一個異常時,它將在except
子句結束時被清除。 -
else
語句的異常不會由之前的except
子句處理 -
finally
指定異常清理程序,如果在try
,except
和else
子句中發生未處理的異常,先暫時保存,至finally
子句末尾重新引發;若finally
子句產生新的異常,被保存的異常被設置為新異常的上下文。
8.5 with語句
with_stmt ::= "with" with_item ("," with_item)* ":" suite
with_item ::= expression ["as" target]
注:with
語句會保證如果__enter__()
方法返回時未發生錯誤,則__exit__()
將總是被調用。
8.6 函數定義
funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")"
["->" expression] ":" suite
decorators ::= decorator+
decorator ::= "@" dotted_name ["(" [argument_list [","]] ")"] NEWLINE
dotted_name ::= identifier ("." identifier)*
parameter_list ::= defparameter ("," defparameter)* "," "/" ["," [parameter_list_no_posonly]]
| parameter_list_no_posonly
parameter_list_no_posonly ::= defparameter ("," defparameter)* ["," [parameter_list_starargs]]
| parameter_list_starargs
parameter_list_starargs ::= "*" [parameter] ("," defparameter)* ["," ["**" parameter [","]]]
| "**" parameter [","]
parameter ::= identifier [":" expression]
defparameter ::= parameter ["=" expression]
funcname ::= identifier
參數說明:
-
decorators
裝飾器組:由多個裝飾器組成 -
decorator
裝飾器- 以點號(屬性)名稱標識裝飾器
- 可以調用形式輸入
argument_list
,即包括位置參數、關鍵字參數等 - 以
NEWLINE
結尾
-
parameter_list
形參列表:- 多個函數形參組成的列表
- 由
*參數
,**參數
構成的參數列表。在*
或*identifier
后的函數形參僅接受關鍵字參數。 - 參數列表中的斜杠字符
/
參數用于分隔位置形參與關鍵字形參,位于/
前的形參不能接受關鍵字參數。
-
defparameter
形參:- 以形參 = 表達式設置默認形參值
特別注意:
- 函數定義是一條可執行語句。將函數名稱綁定至一個函數對象
- 函數定義不會執行函數體,只有當函數調用時才會執行。
- 裝飾器以函數對象作為輸入,求值結果綁定至函數名稱。
- 如果一個形參具有默認值,則后續所有在
*
之前的形參也必須具有默認值。 - 默認形參在執行函數定義時按照從左至右的順序被求值,注意默認形參為可變對象的情況時,通常與預期不一致。
- 形參可以帶有標注
: expression
;函數可以帶有返回標注-> expression
。標注的存在不改變函數語義。 標注值可以作為函數對象的__annotations__
屬性中以對應形參名稱為鍵的字典值被訪問。
8.7 類定義
classdef ::= [decorators] "class" classname [inheritance] ":" suite
inheritance ::= "(" [argument_list] ")"
classname ::= identifier
8.8 協程
async_funcdef ::= [decorators] "async" "def" funcname "(" [parameter_list] ")"
["->" expression] ":" suite
async_for_stmt ::= "async" for_stmt
async_with_stmt ::= "async" with_stmt
- 協程函數:可以在多個位置上掛起與恢復執行。
await
、async for
與async with
只能在協程函數體內部使用。 - async for語句
- async with語句
9 最高層級組件
9.1 完整的Python程序
Python程序會在最小初始化環境中被執行:所有內置模塊和標準模塊均可用但均處于未初始化狀態;僅有sys
,builtins
,__main__
初始化;__main__
模塊提供局部、全局命名空間。
一個完整程序可通過三種形式被傳遞給解釋器:
- 使用 -c 字符串 命令行選項,
- 使用一個文件作為第一個命令行參數,
- 使用標準輸入。
如果文件或標準輸入是一個 tty 設置,解釋器會進入交互模式;否則的話,它會將文件當作一個完整程序來執行。
10 完整語法
原文來自:Python官網的Python 語言參考(3.8.2版本)。
若侵權請聯系刪除