Python_語法及語義

**Python 語法及語義**（Python syntax and semantics），Python 編程語言之語法是一組 Python 的運作編程規則，用於定義 Python 程序如何來編寫與編譯（由運行時系統與程式師來操作）。Python 語言與 Perl、C，以及 Java 有許多相似之處，不過在這些語言之間仍存在著一些明確的差異。

## 設計理念

Python 被設計為一種高度可讀的程式語言。它具有相對排列有致的視覺佈局，並且在其他編程語言使用標點符號的情況下經常使用英文關鍵字。Python 的目標是在其語法設計中保持簡單與一致性，在「Python 之禪」一書中的「宣示」也提到「應該有一種 —— 最好只有一種 —— 明顯的方法來達成 Python 簡單與一致性的目標」。

如上述、Python 的「宣示」即「應該有一種 —— 最好只有一種 —— 明顯的方法來達成 Python 簡單與一致性的目標」；而這個宣示故意跟「Perl」及「Ruby」的宣示「不止只有一種方法可以達成目標」唱反調。

## 關鍵字

Python 有 35 個關鍵字或保留字；這些關鍵字或保留字不能用作標識符。

**註解**

## 首行縮排

Python 使用空白字元來分隔控制流程區塊（遵循越位規則）。 Python 借鑒了其前身 ABC 的這一特性：它使用首行縮排來表示代碼塊的運作，而不是標點符號或關鍵字。

在所謂的 "自由格式"(free-format) 的程式語言中 —— 使用源自 ALGOL 的區塊結構 —— 代碼區塊會使用大括號 (`{ }`) 或關鍵字來區分隔開。在這些程式語言的大多數代碼約定中，程序師通常會在區塊內縮進代碼，使其在視覺上能與周圍的代碼區明白的區分開來。

一個名為 `foo` 的遞迴函數，它傳遞一個參數 `x`，如果參數為 `0`，僅呼叫 `bar` 這個函數；否則將呼叫不同的名為 `baz` 的函數，傳遞參數 `x`，並遞迴呼叫自身，傳遞 `x-1` 為參數，這都可以在 Python 中實現的演算：

並且可以在 C 中用 K&R 縮排樣式寫成如下程式：

不正確的縮排代碼可能會被人誤讀，而不是被編譯器或直譯器解譯。 比如，如果上例中最後一行的函數呼叫 `foo(x - 1)` 會被錯誤地縮排到 `if`/`else` 區塊之外：

造成上例編程無論如何最後一行都會被執行，即使 `x` 為 `0` 亦是如此，結果會導致無限遞迴的現象。

雖然空格和製表鍵都被接受作為縮排的形式，並且可以使用任意倍數的空格，也建議使用空格作為不同的架構區分；並且在標準上建議區分不同的巢狀結構使用 4 個空格的形式（如上例所示），這也是迄今為止最常用的空格佈局形態。從 Python 3 開始，不允許在同一源代碼文件中的連續行上混合空格和製表符，這會導致產生難以發現的錯誤；因為有許多工具無法在視覺上區分空格與製表鍵。

## 資料結構

由於 Python 是一種動態類型的程式語言，因此 Python 值不是一種變量攜帶資料類型信息。 Python 中的所有變量都持有對對象的參照，這些參照被傳遞給函數； 函數不能在其呼叫函數中更改變量參照的值（但請參閱下面的例外情況）。有些人（包括吉多・範羅蘇姆本人）將這種參數傳遞方案稱為 "依物件參照呼叫"。"對象參照" 意味著一個名稱，"傳遞參照" 是一個 "別名"，即是對同一物件的參照副本，就像在 C/C++ 中一樣。物件的值可以在被呼叫的函數中用「別名」改變，比如：

函數 `my_func` 用形式引數 `al` 改變 `alist` 的值，它即是 `alist` 的別名。然而、任何對別名本身進行操作的嘗試都不會對原始對象產生影響。在 Python 中，非最內部局部 (non-innermost-local) 以及未聲明全面 (not-declared-global) 可攫取的名稱都是別名。

在動態類型語言中，Python 進行了適度的類型檢查。 隱式轉換是為數字類型（以及布爾值）定義的，因此可以有效地將複數乘以整數（例如）而沒有顯式轉換。 但是，例如數字和字符串之間沒有隱式轉換； 字符串是需要數字之數學函數的無效參數。

### 基本類型

Python 具有廣泛的基本數據類型。 除了傳統的整數以及浮點數算術外，它透明地支持高精度計算、複數，及十進制數。

### 集合類型

Python 非常有用的方面之的是集合（或容器）類型的概念。 一般來說，集合是一個以易於引用、或則索引的方式包含其他對象的物件。 集合有兩種基本形式：序列與映射。

### 物件系統

在 Python 中，一切都是物件，甚至是類屬。類屬，作為物件，有一個類屬，稱為它們的元類。Python 亦支持多重繼承以及 Mixin。

Python 語言支持對類型以及類屬的廣泛自檢。 可以讀取與比較類型 —— 而所謂的類型是指類型的實例。 物件的屬性可以提取為字典。

## 文字

### 字符串

Python 有各種字符串文字。

#### 普通字符串文字

單引號或雙引號均可用於引用字符串。 與 Unix shell 語言、Perl，或受 Perl 影響的語言（諸如 Ruby 或 Groovy）不同，單引號和雙引號的功能相同，即 $foo 表達式沒有字符串插值。然而，可以通過多種方式進行插值：使用「f-strings」（自 Python 3.6 開始）、使用格式方法或者舊的 % 字符串格式的運算符。

比如，所有這些 Python 的宣告語句：

等價於 Perl 的宣告語句：

語句使用變量 `num` 以及 `printer` 構建一個字符串。

#### 多行字符串文字

還有多行字符串，它們以一系列三個單引號或雙引號開頭及結尾，而其功能類似於 Perl 與 Ruby 中的 Here 文檔。

字符串內插值的一個簡單示例（使用格式的方法）比如：

#### 原始字符串

範例包括：

#### 相鄰字符串文字的串聯

因此

相當於

#### Unicode

從 Python 3.0 開始，源代碼與直譯器的默認字符集都是 UTF-8。在 UTF-8 中，Unicode 字符串的處理方式及傳統的字節字符串類似。這個例子將起如下作用：

### 數字

Python 中的數字文字是屬於普通類型，例如：`0`，`-1`，`3.4`，`3.5e-8`。

### 列表、多元組、集合、字典

Python 具有支持創建容器類型的語法。

列表（類屬列表）是任意類型項目的可變序列，可以使用特殊語法來創建。

或使用普通物件來創建

多元組（類屬元組）是任意類型項目的不可變序列。還有一個特殊的語法來創建多元組

## 運算符

### 算術

在算術上 Python 包括 `+`、`-`、`*`、`/`("真值除法")、`//`(下限除法)、`%`(模數) 以及 `**`(取冪) 運算符，以及它們通常的數學優先級別。在 Python 3 中，`x/y` 執行 "真值除法"(true division)，這表示它總是會回返一個浮點數，即使 x 與 y 都是整除的整數。

接著 `//` 執行整數除法、或_下限除法_，將商數的下限作為整數回返。

在 Python 2 (及大多數其他編程語言) 中，除非明確要求，否則 `x/y` 在執行整數除法時，僅當任一輸入值為浮點數時才回返浮點數。但是，因爲 Python 是一種動態類型的語言；並不總是能夠分辨出正在執行的是哪一個操作，這往往會導致細微的錯誤。從而促使 Python 3 引入 `//` 運算符，並改變 `/` 運算符的語義。

### 比較運算符

比較運算符 (comparison operator)，比如：`==`, `!=`, `<`, `>`, `<=`, `>=`, `is`, `is not`, `in` 及 `not in` 可用於各種運算值的使用上。數字、字符串、序列，以及映射都可以進行比較。在 Python 3 中，不同的類型 (比如 `str` 和 `int`) 沒有一致的相對順序。雖然在 Python 2 中可以比較某個字符串是大於、還是小於某個整數；但這被認為是歷史上的 "設計怪癖"，最終在 Python 3 中被刪除。

諸如 `a < b < c` 之類的 "鍊式比較表達式"(chained comparison expressions) 大致具有它們在數學中的含義，而不是在 C 與類似語言中發現的不尋常含義。這些程式術語是依據順序進行評估與比較。這個操作具有短路求值語義，這表示著一旦判斷明確，就保證評估停止：如果 `a < b` 為假，則永遠不會評估到 `c`，因為表達式不可能再為真。

對於沒有副作用的表達式，`a < b < c` 為等價於 `a < b 與 b < c`。然而，當表達式具有副作用時，也是存在很大差異。`a < f(x) < b` 將只計算 `f(x)` 一次，而 `a < f(x) 以及 f(x) < b`；如果 `a` 的值小於 `f(x)` 將計算兩次，否則只計算一次。

### 邏輯運算符

在所有版本的 Python 裏面，布爾運算符處理零值或空值、諸如 `""`、`0`、`None`、`0.0`、`[]`，以及 `{}` 將被視為」假「；而通常則將非空 (non-empty)、非零值 (non-zero value) 視為 "真"。布爾值 `真` 與 `假` 在 Python 2.2.1 中是作為常數 (從 `1` 及 `0` 產生的子類化) 添加到程式語言裏，並在 Python 3 中變成為完整的關鍵字。二進制 "比較運算符"、諸如 `==` 以及 `>` 則回返 `真` 或 `假` 的信息。

布爾運算符 (boolean operator)`and` 及 `or` 使用最小化求值。例如，`y == 0 或則 x/y > 100` 永遠不會引發被零除之異常錯誤信息。這些 "運算符" 回返最後操作元評估之值，而不是 `真` 或是 `假` 的情形。因此，表達式 `(4 及 5)` 的計算結果為 `5`，而 `(4 或 5)` 的計算結果為 4。因此，表達式 `(4 及 5)` 的計算結果為 `5`，而 `(4 或 5)` 的計算結果為 `4`。

## 函數式編程

如上所述，Python 的另一個優勢是函數式編程風格的可用性。正如所料，這使得使用列表及其他集合更加簡單。

### 理解

### 第一級函數

在 Python 中，函數是可以動態創建以及傳遞的第一級物件。

Python 對匿名函數的有限支持是 `lambda` 建構式。下列範例是對輸入值求平方的匿名函數，使用引數 5 來呼叫 (調用) 的：

Lambda 僅限於包含表達式而不是語句陳述式，儘管 "控制流"(control flow) 仍可以通過使用短路在 lambda 中不太優雅地實現編程，並且更習慣地使用 "條件表達式"(conditional expression)。

### 閉包

### 生成器

### 生成器表達式

在 Python 2.4 中引入的生成器表達式是列表推導式的惰性求值等價式。使用上一節中提供的質數生成器，我們可以定義一個惰性求值方式但不是無限的集合。

### 字典與集合推導式

Python 2.7 及 3.0 通過引入字典與集合推導式來統一所有集合類型，類似於列表推導式：

## 物件

Python 支持大多數面向物件編程 (OOP) 技術。

### With 宣告

關於 `with` 語句可以處理資源的使用，並允許使用者使用 "上下文管理器協議"(Context Manager protocol)。在進入作用域時呼叫一個函數 (`__enter__()`)，而自離開時呼叫另一個函數 (`__exit__()`)。如此可以防止忘記釋放資源，而且還可以處理更複雜的情形、比如在資源使用過程中發生異常時可以釋放資源。"上下文管理器"(Context Managers) 通常與文件、資料庫連接、測試用例等情況一起使用。

### 屬性

屬性允許使用及屬性揭取相同的語法在物件實例上調用專門定義的方法。 定義一些屬性的類屬的一個例子是：

### 描述符

定義三個特殊方法 `__get__(self, instance, owner)`，`__set__(self, instance, value)`，`__delete__(self, instance)`) 中的一個，或多個的類屬可以用作描述符。創建描述符的實例作為第二個類的類成員，使該實例成為第二個類之屬性。

### 類屬與靜態法

Python 允許通過使用 @cla `@classmethod` 及 `@staticmethod` 的修飾模式來創建類方法和靜態方法。類方法的第一個參數是類物件，而不是對實例的自引用。靜態方法沒有特殊的第一個參數。實例及類物件都不會傳遞給靜態方法。

## 異常

在第一個代碼的示例中，遵循 LBYL 的方法，在揭取之前對屬性進行了外顯的檢查：

第二個示例遵循 EAFP 範式:

## 説明與文檔字符串

説明一段代碼：

用多行説明一段代碼：

## 函數註解

函數註解（類型提示）在 PEP3107 中定義。函數註解允許將數據附加到函數的參數以及返回原址。註釋的特性不是由程式語言所定義的，而是留給第三方框架的來進行的。例如，可以編寫一個資料庫來處理靜態類型的程式語言架構：

## 修飾子

修飾子 (裝飾器；修飾符) 是用於修改函數、方法，或則類定義的任何可調用的 Python 物件。修飾子傳遞正被定義的原始物件、並返回修改後的物件；然後將其綁定到定義中的名稱之上。Python 修飾子部分受到 Java 註釋運用的啟發，並且具有類似 Java 的語法；修飾子語法是純粹的語法糖，使用 @ 作為修飾子的關鍵字：

相當於

修飾子是元編程的一種形式； 它們增強了它們修飾的函數或方法的作用。 比如，在下面的示例中，viking\_chorus 可能會導致 menu\_item 每次被呼叫時運行 8 次（參見小品喜劇 (Spam)）： 

函數修飾子的典型用途是創建類方法或靜態方法、添加函數屬性、追蹤、設置前置及後置條件以及同步，不過可以用於更多方面，包括尾遞歸、記憶化；甚至改進其他修飾子的編寫。

修飾子的作用；即是可以經由在主要程式語言相鄰且相關的行之上置放幾個修飾子、進而來帶動主程式鏈接修飾子之間的連繫：

相當於

或者，使用中介架構的變數、如下程式所示：

在上述的例子中，favourite\_colour 修飾子工廠接受一個參數。 修飾子工廠必須返回一個修飾子，然後使用要修飾的物件作為參數來呼叫它：

## 復活節彩蛋

一個隱藏信息，Python 之禪（Python 設計哲學的總結），在嘗試 `import this`(導入 this) 時會顯示出來。

## 註釋

## 參閱

* 列表推導式
* Python 的歷史
* Advice (編程)
* 結構編輯器（語法導向編輯器）
* 置換

## 外部連接

* Python tutorial （頁面存檔備份，存於網際網路檔案館） written by the author of Python, Guido van Rossum.
* PYTHON LISTS — PROGRAMMING REVIEW （頁面存檔備份，存於網際網路檔案館）
* FrontPage - Python Wiki （頁面存檔備份，存於網際網路檔案館）