2. 詞法分析

Python 程式由解析器讀取。解析器的輸入是由詞法分析器生成的標記流。本章描述詞法分析器如何將檔案分解為標記。

Python 將程式文字讀取為 Unicode 程式碼點;原始檔的編碼可以透過編碼宣告指定,預設為 UTF-8,詳情請參閱PEP 3120。如果原始檔無法解碼,則會引發SyntaxError

2.1. 行結構

Python 程式被劃分為多個邏輯行

2.1.1. 邏輯行

邏輯行的末尾由標記 NEWLINE 表示。語句不能跨越邏輯行邊界,除非語法允許 NEWLINE(例如,複合語句中的語句之間)。邏輯行由一個或多個物理行透過遵循顯式或隱式的行連線規則構成。

2.1.2. 物理行

物理行是由行尾序列終止的字元序列。在原始檔和字串中,可以使用任何標準平臺行終止序列 - Unix 形式使用 ASCII LF(換行符)、Windows 形式使用 ASCII 序列 CR LF(回車後跟換行符)或舊 Macintosh 形式使用 ASCII CR(回車)字元。所有這些形式都可以平等使用,而與平臺無關。輸入的末尾也作為最後一個物理行的隱式終止符。

嵌入 Python 時,應使用標準 C 約定來表示換行符(\n 字元,表示 ASCII LF,是行終止符)將原始碼字串傳遞給 Python API。

2.1.3. 註釋

註釋以井號字元(#)開頭,該字元不是字串字面值的一部分,並以物理行的末尾結束。除非呼叫隱式行連線規則,否則註釋表示邏輯行的末尾。註釋會被語法忽略。

2.1.4. 編碼宣告

如果 Python 指令碼的第一行或第二行中的註釋與正則表示式 coding[=:]\s*([-\w.]+) 匹配,則此註釋將被處理為編碼宣告;此表示式的第一組命名了原始碼檔案的編碼。編碼宣告必須單獨出現在一行上。如果是第二行,則第一行也必須是僅包含註釋的行。編碼表達式的推薦形式是

# -*- coding: <encoding-name> -*-

這也受 GNU Emacs 識別,以及

# vim:fileencoding=<encoding-name>

這受 Bram Moolenaar 的 VIM 識別。

如果未找到編碼宣告,則預設編碼為 UTF-8。如果檔案的隱式或顯式編碼為 UTF-8,則初始 UTF-8 位元組順序標記 (b'xefxbbxbf') 將被忽略,而不是語法錯誤。

如果聲明瞭編碼,則編碼名稱必須被 Python 識別(請參閱標準編碼)。該編碼用於所有詞法分析,包括字串字面值、註釋和識別符號。

2.1.5. 顯式行連線

可以使用反斜槓字元(\)將兩個或多個物理行連線成邏輯行,如下所示:當物理行以不屬於字串字面值或註釋的反斜槓結尾時,它將與後面的行連線,形成一個邏輯行,刪除反斜槓和後面的行尾字元。例如

if 1900 < year < 2100 and 1 <= month <= 12 \
   and 1 <= day <= 31 and 0 <= hour < 24 \
   and 0 <= minute < 60 and 0 <= second < 60:   # Looks like a valid date
        return 1

以反斜槓結尾的行不能帶有註釋。反斜槓不會繼續註釋。反斜槓不會繼續標記,但字串字面值除外(即,除了字串字面值之外的標記不能使用反斜槓跨越物理行分割)。反斜槓在字串字面值之外的行上的其他地方是非法的。

2.1.6. 隱式行連線

括號、方括號或大括號中的表示式可以跨越多個物理行進行分割,而無需使用反斜槓。例如

month_names = ['Januari', 'Februari', 'Maart',      # These are the
               'April',   'Mei',      'Juni',       # Dutch names
               'Juli',    'Augustus', 'September',  # for the months
               'Oktober', 'November', 'December']   # of the year

隱式續行可以帶有註釋。續行的縮排不重要。允許使用空白續行。隱式續行之間沒有 NEWLINE 標記。隱式續行也可以出現在三引號字串中(請參見下文);在這種情況下,它們不能帶有註釋。

2.1.7. 空行

僅包含空格、製表符、換頁符以及可能的註釋的邏輯行將被忽略(即,不會生成 NEWLINE 標記)。在互動式輸入語句期間,對空行的處理可能因讀取-求值-列印迴圈的實現而異。在標準互動式直譯器中,完全空白的邏輯行(即,一個甚至不包含空格或註釋的邏輯行)將終止多行語句。

2.1.8. 縮排

邏輯行開頭的起始空格(空格和製表符)用於計算該行的縮排級別,進而用於確定語句的分組。

製表符(從左到右)被替換為一個到八個空格,使得直到幷包括替換的總字元數是八的倍數(這旨在與 Unix 使用的規則相同)。然後,第一個非空白字元之前的總空格數確定行的縮排。縮排不能使用反斜槓跨越多個物理行進行分割;直到第一個反斜槓的空格確定縮排。

如果原始檔以一種使得含義取決於製表符在空格中的值的方式混合使用製表符和空格,則縮排將被拒絕為不一致;在這種情況下,會引發TabError

跨平臺相容性說明: 由於非 UNIX 平臺上文字編輯器的性質,因此在單個原始檔中使用空格和製表符的混合進行縮排是不明智的。還應注意,不同的平臺可能會顯式限制最大縮排級別。

換頁符可能出現在行的開頭;在上面的縮排計算中,它將被忽略。在起始空格中的其他位置出現的換頁符具有未定義的效果(例如,它們可能會將空格計數重置為零)。

連續行的縮排級別用於生成 INDENT 和 DEDENT 標記,使用堆疊,如下所示。

在讀取檔案的第一行之前,將一個零推入堆疊;這將永遠不會再次彈出。推入堆疊的數字將始終從底部到頂部嚴格遞增。在每個邏輯行的開頭,將該行的縮排級別與堆疊的頂部進行比較。如果相等,則不發生任何事情。如果更大,則將其推入堆疊,並生成一個 INDENT 標記。如果更小,則必須是堆疊中出現的數字之一;堆疊上較大的所有數字都將被彈出,並且對於每個彈出的數字,都會生成一個 DEDENT 標記。在檔案末尾,將為堆疊中剩餘的每個大於零的數字生成一個 DEDENT 標記。

這是一個正確(儘管令人困惑)縮排的 Python 程式碼示例

def perm(l):
        # Compute the list of all permutations of l
    if len(l) <= 1:
                  return [l]
    r = []
    for i in range(len(l)):
             s = l[:i] + l[i+1:]
             p = perm(s)
             for x in p:
              r.append(l[i:i+1] + x)
    return r

以下示例顯示了各種縮排錯誤

 def perm(l):                       # error: first line indented
for i in range(len(l)):             # error: not indented
    s = l[:i] + l[i+1:]
        p = perm(l[:i] + l[i+1:])   # error: unexpected indent
        for x in p:
                r.append(l[i:i+1] + x)
            return r                # error: inconsistent dedent

(實際上,前三個錯誤由解析器檢測到;只有最後一個錯誤由詞法分析器發現 — return r 的縮排與從堆疊中彈出的級別不匹配。)

2.1.9. 標記之間的空格

除了在邏輯行的開頭或字串字面值中,空格、製表符和換頁符可以互換使用來分隔標記。僅當兩個標記的串聯可以被解釋為不同的標記時,才需要在兩個標記之間新增空格(例如,ab 是一個標記,但 a b 是兩個標記)。

2.2. 其他標記

除了 NEWLINE、INDENT 和 DEDENT 之外,還存在以下幾類標記:識別符號關鍵字字面值運算子分隔符。空格字元(前面討論的行終止符除外)不是標記,而是用於分隔標記。如果存在歧義,則標記包含從左到右讀取時形成合法標記的最長字串。

2.3. 識別符號和關鍵字

識別符號(也稱為名稱)由以下詞法定義描述。

Python 中識別符號的語法基於 Unicode 標準附件 UAX-31,並根據以下定義進行了詳細說明和更改;另請參閱 PEP 3131 以瞭解更多詳細資訊。

在 ASCII 範圍 (U+0001..U+007F) 內,識別符號的有效字元包括大寫和小寫字母 AZ、下劃線 _,以及(除了第一個字元外)數字 09。 Python 3.0 引入了 ASCII 範圍之外的其他字元(請參閱 PEP 3131)。對於這些字元,分類使用 unicodedata 模組中包含的 Unicode 字元資料庫的版本。

識別符號的長度沒有限制。大小寫是有意義的。

identifier   ::=  xid_start xid_continue*
id_start     ::=  <all characters in general categories Lu, Ll, Lt, Lm, Lo, Nl, the underscore, and characters with the Other_ID_Start property>
id_continue  ::=  <all characters in id_start, plus characters in the categories Mn, Mc, Nd, Pc and others with the Other_ID_Continue property>
xid_start    ::=  <all characters in id_start whose NFKC normalization is in "id_start xid_continue*">
xid_continue ::=  <all characters in id_continue whose NFKC normalization is in "id_continue*">

上面提到的 Unicode 類別程式碼代表:

  • Lu - 大寫字母

  • Ll - 小寫字母

  • Lt - 首字母大寫的字母

  • Lm - 修飾符字母

  • Lo - 其他字母

  • Nl - 字母數字

  • Mn - 非間距標記

  • Mc - 間距組合標記

  • Nd - 十進位制數字

  • Pc - 連線標點符號

  • Other_ID_Start - PropList.txt 中明確的字元列表,以支援向後相容性

  • Other_ID_Continue - 同樣

所有識別符號在解析時都會轉換為 NFKC 正規化;識別符號的比較基於 NFKC。

可以在 https://www.unicode.org/Public/15.1.0/ucd/DerivedCoreProperties.txt 找到一個非規範的 HTML 檔案,其中列出了 Unicode 15.1.0 的所有有效識別符號字元。

2.3.1. 關鍵字

以下識別符號用作語言的保留字或關鍵字,不能用作普通識別符號。它們的拼寫必須與此處寫的完全一致。

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

2.3.2. 軟關鍵字

在 3.10 版本中新增。

有些識別符號僅在特定上下文中保留。這些被稱為軟關鍵字。識別符號 matchcasetype_ 在某些上下文中可以在語法上充當關鍵字,但這種區分是在解析器級別完成的,而不是在標記化時完成的。

作為軟關鍵字,它們在語法中的使用是可能的,同時仍然保持與使用這些名稱作為識別符號名稱的現有程式碼的相容性。

matchcase_match 語句中使用。typetype 語句中使用。

在 3.12 版本中更改: type 現在是一個軟關鍵字。

2.3.3. 保留的識別符號類別

某些類別的識別符號(除了關鍵字)具有特殊的含義。這些類別透過前導和尾隨下劃線字元的模式來識別。

_*

不被 from module import * 匯入。

_

match 語句中的 case 模式中,_ 是一個軟關鍵字,表示一個萬用字元

另外,互動式直譯器使上次求值的結果在變數 _ 中可用。(它儲存在 builtins 模組中,以及內建函式(如 print)一起。)

在其他地方,_ 是一個常規識別符號。它通常用於命名“特殊”項,但它本身對 Python 來說並不特殊。

注意

名稱 _ 通常與國際化結合使用;有關此約定的更多資訊,請參閱 gettext 模組的文件。

它也常用於未使用的變數。

__*__

系統定義的名稱,俗稱“dunder”名稱。這些名稱由直譯器及其實現(包括標準庫)定義。當前系統名稱在 特殊方法名稱 部分和其他地方討論。未來版本的 Python 中可能會定義更多名稱。任何 使用 __*__ 名稱(在任何上下文中),如果不遵循明確記錄的使用方法,都可能在沒有警告的情況下中斷。

__*

類私有名稱。此類別中的名稱在類定義的上下文中使用時,會被重寫為使用經過修改的形式,以幫助避免基類和派生類的“私有”屬性之間的名稱衝突。請參閱 識別符號(名稱) 部分。

2.4. 字面值

字面值是某些內建型別的常量值的表示法。

2.4.1. 字串和位元組字面值

字串字面值由以下詞法定義描述

stringliteral   ::=  [stringprefix](shortstring | longstring)
stringprefix    ::=  "r" | "u" | "R" | "U" | "f" | "F"
                     | "fr" | "Fr" | "fR" | "FR" | "rf" | "rF" | "Rf" | "RF"
shortstring     ::=  "'" shortstringitem* "'" | '"' shortstringitem* '"'
longstring      ::=  "'''" longstringitem* "'''" | '"""' longstringitem* '"""'
shortstringitem ::=  shortstringchar | stringescapeseq
longstringitem  ::=  longstringchar | stringescapeseq
shortstringchar ::=  <any source character except "\" or newline or the quote>
longstringchar  ::=  <any source character except "\">
stringescapeseq ::=  "\" <any source character>
bytesliteral   ::=  bytesprefix(shortbytes | longbytes)
bytesprefix    ::=  "b" | "B" | "br" | "Br" | "bR" | "BR" | "rb" | "rB" | "Rb" | "RB"
shortbytes     ::=  "'" shortbytesitem* "'" | '"' shortbytesitem* '"'
longbytes      ::=  "'''" longbytesitem* "'''" | '"""' longbytesitem* '"""'
shortbytesitem ::=  shortbyteschar | bytesescapeseq
longbytesitem  ::=  longbyteschar | bytesescapeseq
shortbyteschar ::=  <any ASCII character except "\" or newline or the quote>
longbyteschar  ::=  <any ASCII character except "\">
bytesescapeseq ::=  "\" <any ASCII character>

這些產生式中未指明的一個語法限制是,在 stringprefixbytesprefix 和字面值的其餘部分之間不允許有空格。源字元集由編碼宣告定義;如果原始檔中沒有給出編碼宣告,則為 UTF-8;請參閱 編碼宣告 部分。

用通俗易懂的英語來說:兩種型別的字面值都可以用匹配的單引號(')或雙引號(")括起來。它們也可以用匹配的三組單引號或雙引號括起來(這些通常稱為三引號字串)。反斜槓(\)字元用於賦予普通字元(如 n)特殊含義,當轉義時(\n)表示“換行符”。它也可以用於轉義其他具有特殊含義的字元,例如換行符、反斜槓本身或引號字元。請參閱下面的轉義序列,瞭解示例。

位元組字面值總是以 'b''B' 為字首;它們生成 bytes 型別的例項,而不是 str 型別。它們只能包含 ASCII 字元;數值為 128 或更大的位元組必須用轉義符表示。

字串和位元組字面值都可以選擇以字母 'r''R' 為字首;這種結構分別稱為原始字串字面值原始位元組字面值,並將反斜槓視為字面字元。因此,在原始字串字面值中,'\U''\u' 轉義符不被特殊處理。

在 3.3 版本中新增: 原始位元組字面值的 'rb' 字首已新增為 'br' 的同義詞。

為了簡化 Python 2.x 和 3.x 雙程式碼庫的維護,重新引入了對 unicode 舊字面值(u'value')的支援。有關更多資訊,請參閱 PEP 414

字首中帶有 'f''F' 的字串字面值是一個格式化字串字面值;請參閱 f-字串'f' 可以與 'r' 組合使用,但不能與 'b''u' 組合使用,因此可以使用原始格式化字串,但不能使用格式化位元組字面值。

在三引號字面值中,允許使用未轉義的換行符和引號(並保留),但一行中三個未轉義的引號會終止字面值。(“引號”是用於開啟字面值的字元,即 '"。)

2.4.1.1. 轉義序列

除非存在 'r''R' 字首,否則字串和位元組字面值中的轉義序列將根據與標準 C 使用的規則相似的規則進行解釋。識別的轉義序列是

轉義序列

含義

備註

\<換行符>

反斜槓和換行符被忽略

(1)

\\

反斜槓 (\)

\'

單引號 (')

\"

雙引號 (")

\a

ASCII 響鈴 (BEL)

\b

ASCII 退格 (BS)

\f

ASCII 換頁 (FF)

\n

ASCII 換行 (LF)

\r

ASCII 回車 (CR)

\t

ASCII 水平製表符 (TAB)

\v

ASCII 垂直製表符 (VT)

\ooo

八進位制值為 ooo 的字元

(2,4)

\xhh

十六進位制值為 hh 的字元

(3,4)

僅在字串字面值中識別的轉義序列有

轉義序列

含義

備註

\N{name}

Unicode 資料庫中名為 name 的字元

(5)

\uxxxx

16 位十六進位制值為 xxxx 的字元

(6)

\Uxxxxxxxx

32 位十六進位制值為 xxxxxxxx 的字元

(7)

備註

  1. 可以在行末新增反斜槓以忽略換行符

    >>> 'This string will not include \
    ... backslashes or newline characters.'
    'This string will not include backslashes or newline characters.'
    

    可以使用三引號字串或圓括號和字串字面值拼接來實現相同的結果。

  2. 與標準 C 語言一樣,最多接受三個八進位制數字。

    3.11 版本更改: 大於 0o377 的八進位制轉義會產生一個 DeprecationWarning

    3.12 版本更改: 大於 0o377 的八進位制轉義會產生一個 SyntaxWarning。在未來的 Python 版本中,它們最終會變成 SyntaxError

  3. 與標準 C 語言不同,必須正好是兩位十六進位制數字。

  4. 在位元組字面值中,十六進位制和八進位制轉義表示具有給定值的位元組。在字串字面值中,這些轉義表示具有給定值的 Unicode 字元。

  5. 3.3 版本更改: 添加了對名稱別名 [1] 的支援。

  6. 必須正好是四位十六進位制數字。

  7. 任何 Unicode 字元都可以用這種方式編碼。必須正好是八位十六進位制數字。

與標準 C 語言不同,所有無法識別的轉義序列都會保留在字串中,不會更改,即反斜槓會保留在結果中。(此行為在除錯時很有用:如果轉義序列輸入錯誤,則更容易識別出損壞的輸出。)還需要注意的是,僅在字串字面值中識別的轉義序列屬於位元組字面值中無法識別的轉義序列的類別。

3.6 版本更改: 無法識別的轉義序列會產生一個 DeprecationWarning

3.12 版本更改: 無法識別的轉義序列會產生一個 SyntaxWarning。在未來的 Python 版本中,它們最終會變成 SyntaxError

即使在原始字面值中,引號也可以用反斜槓轉義,但反斜槓會保留在結果中;例如,r"\"" 是一個有效的字串字面值,由兩個字元組成:一個反斜槓和一個雙引號;r"\" 不是有效的字串字面值(即使是原始字串也不能以奇數個反斜槓結尾)。具體而言,原始字面值不能以單個反斜槓結尾(因為反斜槓會轉義後面的引號字元)。另請注意,後跟換行符的單個反斜槓會被解釋為字面值的一部分,而不是行繼續符。

2.4.2. 字串字面值拼接

允許多個相鄰的字串或位元組字面值(以空格分隔),可以使用不同的引號約定,它們的含義與它們的拼接相同。因此,"hello" 'world' 等價於 "helloworld"。此功能可用於減少所需反斜槓的數量、方便地跨長行拆分長字串,甚至可以向字串的某些部分添加註釋,例如

re.compile("[A-Za-z_]"       # letter or underscore
           "[A-Za-z0-9_]*"   # letter, digit or underscore
          )

請注意,此功能是在語法級別定義的,但在編譯時實現的。“+”運算子必須用於在執行時拼接字串表示式。另請注意,字面值拼接可以為每個元件使用不同的引號樣式(甚至混合原始字串和三引號字串),並且格式化的字串字面值可以與普通字串字面值拼接。

2.4.3. f-字串

在 3.6 版本中新增。

格式化字串字面值f-字串是以 '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 | replacement_field)*
literal_char      ::=  <any code point except "{", "}" or NULL>

花括號之外的字串部分按字面意思處理,只是任何雙花括號 '{{''}}' 都將替換為相應的單個花括號。單個左花括號 '{' 標記一個替換欄位,該欄位以 Python 表示式開頭。要在計算後同時顯示錶達式文字及其值(在除錯時很有用),可以在表示式後新增等號 '='。可以跟一個由感嘆號 '!' 引入的轉換欄位。還可以追加一個由冒號 ':' 引入的格式說明符。替換欄位以右花括號 '}' 結尾。

格式化字串字面值中的表示式被視為用括號括起來的常規 Python 表示式,但有一些例外。不允許空表示式,並且 lambda 和賦值表示式 := 都必須用顯式括號括起來。每個表示式都在格式化字串字面值出現的上下文中求值,從左到右依次計算。替換表示式可以在單引號和三引號 f-字串中都包含換行符,並且它們可以包含註釋。替換欄位中 # 之後的所有內容都是註釋(甚至是右花括號和引號)。在這種情況下,替換欄位必須在不同的行中關閉。

>>> f"abc{a # This is a comment }"
... + 3}"
'abc5'

3.7 版本更改: 在 Python 3.7 之前,由於實現問題,在格式化字串字面值中的表示式中不允許使用 await 表示式和包含 async for 子句的推導式。

3.12 版本更改: 在 Python 3.12 之前,不允許在 f-字串替換欄位內使用註釋。

當提供等號 '=' 時,輸出將包含表示式文字、'=' 和計算後的值。左花括號 '{' 之後、表示式內部和 '=' 之後的所有空格都將保留在輸出中。預設情況下,'=' 會導致提供表示式的 repr(),除非指定了格式。當指定格式時,預設使用表示式的 str(),除非聲明瞭轉換 '!r'

3.8 版本新增: 等號 '='

如果指定了轉換,則會在格式化之前轉換表示式的計算結果。轉換 '!s' 會對結果呼叫 str()'!r' 會呼叫 repr()'!a' 會呼叫 ascii()

然後使用 format() 協議格式化結果。格式說明符被傳遞給表示式或轉換結果的 __format__() 方法。省略格式說明符時,會傳遞一個空字串。然後將格式化後的結果包含在整個字串的最終值中。

頂級格式說明符可能包含巢狀的替換欄位。這些巢狀欄位可能包含它們自己的轉換欄位和格式說明符,但不能包含更深層次的巢狀替換欄位。格式說明符微語言str.format() 方法使用的微語言相同。

可以拼接格式化的字串字面值,但替換欄位不能跨多個字面值拆分。

格式化字串字面量的一些示例

>>> name = "Fred"
>>> f"He said his name is {name!r}."
"He said his name is 'Fred'."
>>> f"He said his name is {repr(name)}."  # repr() is equivalent to !r
"He said his name is 'Fred'."
>>> width = 10
>>> precision = 4
>>> value = decimal.Decimal("12.34567")
>>> f"result: {value:{width}.{precision}}"  # nested fields
'result:      12.35'
>>> today = datetime(year=2017, month=1, day=27)
>>> f"{today:%B %d, %Y}"  # using date format specifier
'January 27, 2017'
>>> f"{today=:%B %d, %Y}" # using date format specifier and debugging
'today=January 27, 2017'
>>> number = 1024
>>> f"{number:#0x}"  # using integer format specifier
'0x400'
>>> foo = "bar"
>>> f"{ foo = }" # preserves whitespace
" foo = 'bar'"
>>> line = "The mill's closed"
>>> f"{line = }"
'line = "The mill\'s closed"'
>>> f"{line = :20}"
"line = The mill's closed   "
>>> f"{line = !r:20}"
'line = "The mill\'s closed" '

允許在替換欄位中重用外部 f 字串的引號型別

>>> a = dict(x=2)
>>> f"abc {a["x"]} def"
'abc 2 def'

在 3.12 版本中更改: 在 Python 3.12 之前,在替換欄位中重用外部 f 字串的相同引號型別是不可能的。

反斜槓也允許在替換欄位中使用,並且其求值方式與任何其他上下文中相同

>>> a = ["a", "b", "c"]
>>> print(f"List a contains:\n{"\n".join(a)}")
List a contains:
a
b
c

在 3.12 版本中更改: 在 Python 3.12 之前,反斜槓不允許在 f 字串替換欄位中使用。

格式化字串字面量不能用作文件字串,即使它們不包含表示式。

>>> def foo():
...     f"Not a docstring"
...
>>> foo.__doc__ is None
True

另請參閱 PEP 498,其中提出了新增格式化字串字面量的建議,以及 str.format(),它使用相關的格式字串機制。

2.4.4. 數值字面量

有三種類型的數值字面量:整數、浮點數和虛數。沒有複數字面量(複數可以透過將實數和虛數相加形成)。

請注意,數值字面量不包括符號;像 -1 這樣的短語實際上是一個由一元運算子“-”和字面量 1 組成的表示式。

2.4.5. 整數字面量

整數字面量由以下詞法定義描述

integer      ::=  decinteger | bininteger | octinteger | hexinteger
decinteger   ::=  nonzerodigit (["_"] digit)* | "0"+ (["_"] "0")*
bininteger   ::=  "0" ("b" | "B") (["_"] bindigit)+
octinteger   ::=  "0" ("o" | "O") (["_"] octdigit)+
hexinteger   ::=  "0" ("x" | "X") (["_"] hexdigit)+
nonzerodigit ::=  "1"..."9"
digit        ::=  "0"..."9"
bindigit     ::=  "0" | "1"
octdigit     ::=  "0"..."7"
hexdigit     ::=  digit | "a"..."f" | "A"..."F"

除了可用記憶體中可以儲存的內容外,整數字面量的長度沒有限制。

下劃線在確定字面量的數值時會被忽略。它們可以用於對數字進行分組,以增強可讀性。一個下劃線可以出現在數字之間,以及像 0x 這樣的基數說明符之後。

請注意,非零十進位制數中的前導零是不允許的。這是為了與 C 風格的八進位制字面量進行消除歧義,Python 在 3.0 版本之前使用過這種字面量。

一些整數字面量的示例

7     2147483647                        0o177    0b100110111
3     79228162514264337593543950336     0o377    0xdeadbeef
      100_000_000_000                   0b_1110_0101

在 3.6 版本中更改: 現在允許在字面量中使用下劃線進行分組。

2.4.6. 浮點數字面量

浮點數字面量由以下詞法定義描述

floatnumber   ::=  pointfloat | exponentfloat
pointfloat    ::=  [digitpart] fraction | digitpart "."
exponentfloat ::=  (digitpart | pointfloat) exponent
digitpart     ::=  digit (["_"] digit)*
fraction      ::=  "." digitpart
exponent      ::=  ("e" | "E") ["+" | "-"] digitpart

請注意,整數部分和指數部分始終使用基數 10 進行解釋。例如,077e010 是合法的,並表示與 77e10 相同的數字。浮點數字面量的允許範圍取決於具體實現。與整數字面量一樣,支援使用下劃線進行數字分組。

一些浮點數字面量的示例

3.14    10.    .001    1e100    3.14e-10    0e0    3.14_15_93

在 3.6 版本中更改: 現在允許在字面量中使用下劃線進行分組。

2.4.7. 虛數字面量

虛數字面量由以下詞法定義描述

imagnumber ::=  (floatnumber | digitpart) ("j" | "J")

虛數字面量產生一個實部為 0.0 的複數。複數表示為一對浮點數,並且對其範圍有相同的限制。要建立一個具有非零實部的複數,請將其新增一個浮點數,例如 (3+4j)。一些虛數字面量的示例

3.14j   10.j    10j     .001j   1e100j   3.14e-10j   3.14_15_93j

2.5. 運算子

以下標記是運算子

+       -       *       **      /       //      %      @
<<      >>      &       |       ^       ~       :=
<       >       <=      >=      ==      !=

2.6. 分隔符

以下標記在語法中用作分隔符

(       )       [       ]       {       }
,       :       !       .       ;       @       =
->      +=      -=      *=      /=      //=     %=
@=      &=      |=      ^=      >>=     <<=     **=

句點也可以出現在浮點數和虛數字面量中。三個句點的序列作為省略號字面量具有特殊含義。列表的後半部分,即增強賦值運算子,在詞法上用作分隔符,但也會執行操作。

以下可列印的 ASCII 字元作為其他標記的一部分具有特殊含義,或者對詞法分析器具有其他重要意義

'       "       #       \

以下可列印的 ASCII 字元在 Python 中未使用。它們出現在字串字面量和註釋之外是無條件錯誤

$       ?       `

腳註