Python官方語法學習

通讀了Python官網的語法說明文檔。原文來自:Python 語言參考(3.8.2版本)。在此,將原文的要點進行記錄與分享。


1 概述


2 詞法分析

Python 程序由一個解析器讀取。輸入到解析器的是一個由詞法分析器所生成的形符流。Python 會將讀取的程序文本轉為 Unicode 碼點;源文件的文本編碼可由編碼聲明指定,默認為 UTF-8。

2.1 行結構

  1. 邏輯行NEWLINE形符表示。
    • 語句不能跨邏輯行。
    • 邏輯行可由多個物理行按規則拼接
  2. 物理行以換行字符終止,如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

特殊的標識符

  1. _*:以下劃線字符_開始的標識符不會被import語句from module import *導入。
  2. __*__:以雙下劃線字符開始并結尾的標識符為系統定義的名稱,特殊方法對于的名稱
  3. __*:以雙下劃線開始的標識符是類的私有名稱,會被類定義隱式的轉換。

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>

注:

  1. ! 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 標準類型層級

  1. None

  2. NotImplemented
    邏輯值為真

  3. Ellipsis
    邏輯值為真

  4. numbers.Number

    • numbers.Integeral
      • 整形(int)
      • 布爾型(bool)
    • numbers.Real(float)
    • numbers.Complex(complex)
  5. 序列: 有限有序集,支持len(),切片a[i:j],擴展切片a[i:j:k]

    • 不可變序列:
      • 字符串str
      • 元組
      • 字節串bytes
    • 可變序列:
      • 列表
      • 字節數值bytearray
      • 擴展模塊arraycollections
  6. 集合類型:無序有限集,支持迭代,支持len()

    • 集合set()
    • 凍結集合frozenset()
  7. 映射:任意索引類型的有限集合,支持下標a[k]用于賦值或del語句,支持len()

    • 字典
  8. 可調用類型

    • 用戶定義函數,特殊屬性:

      1. __doc__ 可寫
      2. __name__ 可寫
      3. __qualname__ 可寫,函數限定名稱,顯式從模塊開始的層級
      4. __module__ 可寫,函數所述模塊的名稱
      5. __defaults__ 可寫,默認參數值構成的元組
      6. __code__ 可寫,變異后的函數體代碼
      7. __globals__ 只讀,函數所屬模塊的全局命名空間字典引用
      8. __dict__ 可寫,命名空間支持的函數屬性
      9. __closure__ 只讀
      10. __annotations__ 可寫,包含參數標注的自定
      11. __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__()使類實例可調

  9. 模塊

    • 具有字典對象實現的命名空間,也是模塊中函數__globals__所引用的字典
    • 可寫屬性:__name____doc____annotations____file__
    • 只讀屬性__dict__
  10. 自定義類

    • 每個類都通過字典實現獨立的命名空間,類屬性在字典中查找
    • 特別屬性:__name____module__類所在模塊,__dict____bases__包含基類的元組,__doc____annotations__
  11. 類實例

    • 通過調用類對象創建,每個類實例通過字典實現獨立的命名空間。
    • 若為找到類屬性,而對象對應的類具有__getattr__()方法則會調用該方法。
    • 屬性賦值與刪除會更新實例字典,但不更新類字典。若類具有__setattr__()__delattr()__則調用方法而不直接更新實例字典
    • 特殊屬性:__dict____class__
  12. I/0對象

  13. 內部類型(定義可能在未來解釋器版本中變化)

    • 代碼對象
      • 編譯為字節的可執行Python代碼,或稱bytecode
      • vs函數對象,函數對象具有全局對象的引用,代碼對象不包含上下文
    • 幀對象:表示執行幀
    • 回溯對象:表示異常的棧跟蹤記錄。
    • 切片對象:表示__getitem__()方法得到的切片,
    • 靜態方法對象:
      • 為對任意其它對象的封裝,靜態方法對象自身是不可調用的。
      • 從類或類實例中獲得的靜態方法對象時,獲得的是被封裝的對象。
      • 可由staticmethod()構造器創建
    • 類方法對象:
      • 對其他對象的封裝。
      • 可由classmethod()構造器創建。

3.3 特殊方法

3.3.1 基本定制Basic customization

  1. object.__new__(cls[,...])
    • 創建cls類的新實例,__new__()總是一個靜態方法。返回值應為新對象(通常為cls)實例
    • 典型的實現總有super().__new__(cls[, ...])調用。
    • 如果__new__()發返回了一個cls的實例或者子類,則新實例將調用__init__(self[, ...])進行初始化
    • __new__()沒有返回cls的實例,則不會有__init__()調用
    • 用以對int,str或tuple等子類的自定義;用以創建唯一對象singleton
  2. object.__init__(self[, ...])
    • 其參數與傳遞給構造表達器的參數相同。
    • 應確保基類正確初始化super().__init__([args...])
    • 返回值為None
  3. object.__del__(self)
    • 在實例被銷毀時調用
    • 派生類需確保基類的__del__()正確被調用
    • 注:del xx的引用計數減一;當引用計數為零時,才可能執行x.__del__()
  4. object.__repr__(self)
    • 若可能,使用輸出的字符串能重建相同取值的對象;若不可能則返回形如<...一些有用信息...>的字符串
  5. object.__str__(self):一種非正式或格式良好的字符串
  6. object.__bytes__(self):返回bytes對象
  7. object.__format__(self, format_spec):對象的格式化字符串顯示
  8. 比較方法
    • object.__lt__(self, other)
    • object.__le__(self, other)
    • object.__eq__(self, other)
    • object.__ne__(self, other)
    • object.__gt__(self, other)
    • object.__ge__(self, other)
    • 注:當比較操作的左操作數未實現相關函數,而右操作數有實現,則調用右操作數的方法;當右操作數是左操作數的子類時,優先有操作數的方法
  9. object.__hash__(self)
    • 用于對哈希集setfrozensetdict執行哈希函數hash()。建議將參與比較的對象組件打包為元組整體進行hash計算
    • __eq__()
      • 用戶定義類默認有__eq__()__hash__()方法,確保當x==y時意味著x is yhash(x)==hash(y)
      • 若僅定義__eq__()時,則將__hash__()隱式設置為None;若須保留父類的__hash__()實現,須在類中明確__hash__ = <ParentClass>.__hash__
      • 若未定義__eq__()則不應定義__hash__();若定義__eq__()同時定義了可變對象也不應定義__hash__(),否則對象可能至于錯誤的哈希桶中。
      • 若未定義__eq__()時也不需要默認的__hash__(),則應在類中明確__hash__ = None
    • 注: 在str與bytes對象的hash值由隨機數加鹽,在單獨的python進程中是一致的。
  10. object.__bool__(self)
    • 若類未定義__bool__()也未定義__len__()則實例邏輯值為真

3.3.2 屬性訪問

  1. object.__getattr__(self, name)
    • 當默認屬性訪問失敗時調用:
      • 可能由于__getattribute__()時 ,name非實例屬性
      • 或者對于name特性調用__get__()
  2. object.__getattribute__(self, name)
    • 類實例屬性訪問調用。為避免方法的無限遞歸,總是調用相同名稱的基類方法實現
  3. object.__setattr__(self, name, value)
    • 當實例屬性被賦值時調用。正常實現是調用相同名稱的基類方法
  4. object.__delattr__(self, name)
    • __setattr__()效果范圍類似,僅在del obj.name時生效
  5. 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)的實例是其他所有類的成員時,這些特殊方法才有效

  1. object.__get__(self,instance,owner=None)
    • 實現所有者類屬性/類實例屬性的方法
  2. object.__set__(self,instance,value)
    • 設置instance指向的屬性值為新值
    • 使用__set__()__delete__()將描述器變為數據描述器
  3. object.__delete__(self,instance)
  4. 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__

  1. object.__slots__
    • slots用以顯示聲明數據成員,禁止創建__dict__以及__weakref__除非顯示聲明或在父類中可用.
    • 繼承一個未定義slots的類時,實例的__dict____weakref__總是可訪問的。

3.3.3 類創建

classmethod object.__init_subclass__(cls)

  • 當一個類繼承自其它類時,基類的init_subclass會被調用。
  • 基類控制子類的特性,相較于元類更加靈活
  • 隱式的classmethod

元類

默認情況,類是由type()構建type(name,bases,dict)。在類創建定義中傳入metaclass關鍵字參數,控制類創建使用的元類。

  1. 解析MRO條目
  2. 確定適當的元類
    • 若沒有基類且沒有顯示指定元類,使用type()
    • 若給出顯示的元類且不是type()的實例,則直接用作元類
    • 若給出一個type()實例作為元類,或者定義了基類,則使用最近派生的元類
  3. 準備類命名空間
    • 若元類有__prepare__屬性,則以namespace = metaclass.__prepare__(name,bases,**kwds)調用,namespace傳遞給元類的__new__
    • 元類的__prepare__須顯式聲明為classmethod
    • __prepare__返回的命名空間返回給__new__,但最終類對象創建時,命名空間拷貝至新的只讀代理dict中,作為類對象的字典。
  4. 執行類主體
  5. 創建類對象
    • 執行元類__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() 應當迭代對象的鍵;對于序列,則應當迭代其中的值

  1. object.__len__(self)
  2. object.__length_hint__(self)(可選)
  3. object.__getitem__(self,key)
  4. object.__setitem__(self,key,value)
  5. object.__delitem__(self,key)
  6. object.__missing__(self,key)(在getitem找不到鍵時調用)
  7. object.__iter__(self)
  8. object.__reversed__(self)
  9. 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屬性將指向返回值。
協程也具有下面列出的方法,它們類似于生成器的對應方法。但是,與生成器不同,協程并不直接支持迭代。

  1. coroutine.send(value)開始或恢復協程的執行.
  2. coroutine.throw(type[,value[,traceback]])在協程內引發指定的異常。
  3. coroutine.close()此方法會使得協程清理自身并退出

3.4.3 異步迭代器Asynchronous Iterators

異步迭代器可以在__anext__方法中調用異步代碼。

  1. object.__aiter__(self)返回一個異步迭代器對象
  2. object.__anext__(self)返回一個可等待對象的下一個結果值,或StopAsyncIteration

3.4.4 異步上下文管理器

異步上下文管理器可在async with語句中使用,需要定義__aenter____aexit__方法。


4 執行模型

4.1 程序結構

代碼塊被作為一個單元來執行:模塊、函數體、類定義。內置函數eval()exec()的字符串參數也是代碼塊。

代碼塊在執行幀中被執行,一個幀包含某些管理信息并決定代碼塊執行后將如何繼續執行。

4.2 命名與綁定

4.2.1 名稱綁定

  1. 名稱用于指代對象,通過綁定操作引入:函數的形參,import語句,類與函數定義名稱,被表達式賦值的目標,for循環開始,withexcept語句的as后。
  2. import語句from ... import *將模塊定義的所有導入模塊綁定,這種形式綁定僅可用于模塊層級。
  3. del語句的目標是解除目標綁定。
  4. 每條賦值語句或導入語句均發生在類/函數內部定義的代碼塊中,或者在模塊層級(最高層級的代碼塊)
  5. 名稱綁定在代碼塊中,則為代碼塊的局部變量,除非聲明nonlocalglobal。若名稱綁定在模塊層級,則為全局變量(模塊代碼塊的變量即為局部變量又為全局變量。)如果變量在一個代碼塊中使用但是沒有定義,則為自由變量

4.2.2 名稱的解析

  1. 作用域定義了代碼塊中名稱的可見性。如果代碼塊定義局部變量,其作用域包括該代碼塊。內部代碼塊會屏蔽外部代碼塊的相同名稱綁定。
  2. 環境指對一個代碼塊可見的所有作用域的集合。當一個名稱在代碼塊中使用時,由它最近的作用域解析。
  3. 一個代碼塊內任何位置的名稱綁定導致整個代碼塊對該名稱的引用均在此代碼塊內。
  4. global語句在代碼塊中表示,所有對該語句指定名稱的使用都是最高層級命名空間對該名稱的綁定引用。最高層級命名空間就是全局命名空間,包含:模塊命名空間、內置命名空間。global語句必須位于所有指定名稱使用之前
  5. nonlocal語句使名稱指向之前的最近包含函數作用域中的綁定變量
  6. 模塊的作用域在模塊第一次被導入時自動創建,一個腳本的主模塊總是被命名為__main__
  7. 類定義代碼塊以及exec()eval()參數的名稱解析是特殊情況。未綁定的局部變量會在全局命名空間查找。?類代碼塊定義的名稱的作用域限制在類代碼塊中,不會擴展到方法(包括推導式與生成器表達式)中。

4.2.3 內置命名空間與受限的執行

與代碼塊執行相關的內置命名空間是通過全局命名空間中的builtins來找到。在__main__模塊中,builtins就是內置模塊builtins;在其它模塊中builtinsbuiltins模塊字典的別名

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根據導入模塊的完整限定名稱開始所示。一個指向子模塊的帶點號路徑將從父包開始依次導入。

  1. 模塊緩存:
    • sys.modules緩存之前所有導入的模塊。
    • sys.modules鍵值對應的值為需要導入的模塊。刪除鍵值會是模塊緩存的條目無效。
  2. 查找器:
    • 查找器的任務是確定是否能使用其所知的策略找到該名稱的模塊。
    • Python包含多個默認的查找器:第一個負責定位內置模塊;第二個負責定位凍結模塊;第三個負載在import path(通常來自sys.path,子包還包含上級包__path__)中搜索模塊。
    • 查找器返回一個模塊的模塊規格說明(module spec),以供后續加載過程使用
  3. 導入鉤子(Import hooks):
    • 實現導入機制的可擴展性,包含兩種鉤子:元鉤子(meta hooks)導入路徑鉤子(import path hooks)
    • 元鉤子導入開始時被調用(除sys.modules緩存查找外,其它導入過程尚未發生)。能夠重載查找器特性。元鉤子注冊通過向sys.meta_path添加查找器對象完成。(元鉤子包含三個默認查找器BuiltinImporter,FrozenImporter,PathFinder實現上述Python默認查找器功能)
    • 導入路徑鉤子在遇到所關聯的路徑條目時被調用。通過向sys.path_hooks添加可調用對象完成。(通常被PathFinder在查找時使用)
  4. 元路徑查找器:
    • sys.modules找不到模塊時,Python接著搜索sys.meta_path元路徑查找器。元路徑查找器必須實現find_spec()方法。
    • sys.meta_path處理過程到達列表末尾仍未返回說明,則放棄導入過程。

5.4 加載

在加載器執行模塊代碼前,先將模塊增加至sys.modules中。模塊加載委托加載器執行exec_module()load_modules()進行。

  1. 子模塊:當導入spam.foo之后,在spam中將有一個子模塊foo的屬性。
  2. 模塊規格說明:作為模塊對象的__spec__屬性對外公開(參見importlib
  3. 模塊屬性:
    • 導入機制在加載期間根據模塊規格說明填充以下屬性,在加載器執行模塊前完成
    • __name__完整限定名稱,在導入系統中唯一標識模塊
    • __loader__加載器
    • __package__可以與name取值相同,對于子模塊應設為父包名
    • __spec__
    • __path__模塊為包是必須設置,必須有字符串組成的可迭代對象,于子包導入期間使用。
    • __file__可選屬性,文件位置
    • __cached__可選屬性,編譯緩存文件位置
  4. 模塊的repr
  5. 緩存字節碼:使用--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
  1. identifier標識符
  2. literal字面值
  3. enclosure附件

附件包括:

  1. parenth_form帶括號的形式,by starred_expression
  2. comprehesion推導式,by assignment_expression
  3. list_display列表的顯示,by starred_listcomprehension
  4. set_display集合的顯示,by starred_listcomprehension
  5. dict_display字典的顯示,by expression`
  6. generator_expression生成器表達式,by expression`
  7. yield_atomyield表達式,byexpression_listexpression

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表達式的結果
    • 返回生成器的下一個值
  • generator.throw(type[,value[,traceback]])
    • 在生成器暫停位置印發type類型異常
  • generator.close()
    • 在稱長期函數暫停位置引發GeneratorExit

6.3 原型Primary

primary ::=  atom | attributeref | subscription | slicing | call

原型表示編程語言中最緊密的綁定操作。

  1. atributeref屬性引用
  2. subscription下標抽取
  3. slicing切片
  4. 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 復合語句

復合語句是包含其它語句(語句組)的語句;它們會以某種方式影響或控制所包含其它語句的執行。

  • ifwhilefor語句用來實現傳統的控制流程構造。
  • 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子句的子句體如果存在將會被執行,并終止循環。

  1. for循環子句頭會對目標列表的變量進行賦值,將覆蓋變量的賦值(包括循環體內的賦值)
  2. 目標列表的名稱在循環結束時不會被刪除,但是如果迭代序列為空,名稱將不會被賦值。

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指定異常清理程序,如果在tryexceptelse子句中發生未處理的異常,先暫時保存,至 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

參數說明:

  1. decorators裝飾器組:由多個裝飾器組成
  2. decorator裝飾器
    • 以點號(屬性)名稱標識裝飾器
    • 可以調用形式輸入argument_list,即包括位置參數、關鍵字參數等
    • NEWLINE結尾
  3. parameter_list形參列表:
    • 多個函數形參組成的列表
    • *參數**參數 構成的參數列表。在**identifier后的函數形參僅接受關鍵字參數。
    • 參數列表中的斜杠字符/參數用于分隔位置形參與關鍵字形參,位于/前的形參不能接受關鍵字參數。
  4. defparameter形參:
    • 形參 = 表達式設置默認形參值

特別注意:

  1. 函數定義是一條可執行語句。將函數名稱綁定至一個函數對象
  2. 函數定義不會執行函數體,只有當函數調用時才會執行。
  3. 裝飾器以函數對象作為輸入,求值結果綁定至函數名稱。
  4. 如果一個形參具有默認值,則后續所有在*之前的形參也必須具有默認值。
  5. 默認形參在執行函數定義時按照從左至右的順序被求值,注意默認形參為可變對象的情況時,通常與預期不一致。
  6. 形參可以帶有標注: 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
  1. 協程函數:可以在多個位置上掛起與恢復執行。awaitasync forasync with只能在協程函數體內部使用。
  2. async for語句
  3. async with語句

9 最高層級組件

9.1 完整的Python程序

Python程序會在最小初始化環境中被執行:所有內置模塊和標準模塊均可用但均處于未初始化狀態;僅有sysbuiltins__main__初始化;__main__模塊提供局部、全局命名空間。

一個完整程序可通過三種形式被傳遞給解釋器:

  1. 使用 -c 字符串 命令行選項,
  2. 使用一個文件作為第一個命令行參數,
  3. 使用標準輸入。

如果文件或標準輸入是一個 tty 設置,解釋器會進入交互模式;否則的話,它會將文件當作一個完整程序來執行。

10 完整語法

原文來自:Python官網的Python 語言參考(3.8.2版本)。
若侵權請聯系刪除

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,363評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,497評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,305評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,962評論 1 311
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,727評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,193評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,257評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,411評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,945評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,777評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,978評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,519評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,216評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,657評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,960評論 2 373

推薦閱讀更多精彩內容

  • 這是16年5月份編輯的一份比較雜亂適合自己觀看的學習記錄文檔,今天18年5月份再次想寫文章,發現簡書還為我保存起的...
    Jenaral閱讀 2,805評論 2 9
  • 寫在前面的話 代碼中的# > 表示的是輸出結果 輸入 使用input()函數 用法 注意input函數輸出的均是字...
    FlyingLittlePG閱讀 2,791評論 0 8
  • 要點: 函數式編程:注意不是“函數編程”,多了一個“式” 模塊:如何使用模塊 面向對象編程:面向對象的概念、屬性、...
    victorsungo閱讀 1,548評論 0 6
  • importUIKit classViewController:UITabBarController{ enumD...
    明哥_Young閱讀 3,850評論 1 10
  • 周一晚辦公班主任開會,周二質量分析,周三經驗交流會…… 開了三天會總算給點福利了:今兒的會看視頻,一會兒《亮劍》,...
    格乃閱讀 894評論 16 21