2. 詞法分析?

Python 程序由 解析器 讀取,輸入解析器的是 詞法分析器 生成的 形符 流。本章介紹詞法分析器怎樣把文件拆成形符。

Python 將讀取的程序文本轉(zhuǎn)為 Unicode 代碼點(diǎn);編碼聲明用于指定源文件的編碼,默認(rèn)為 UTF-8,詳見 PEP 3120。源文件不能解碼時(shí),觸發(fā) SyntaxError。

2.1. 行結(jié)構(gòu)?

Python 程序可以拆分為多個(gè) 邏輯行

2.1.1. 邏輯行?

NEWLINE 形符表示結(jié)束邏輯行。語句不能超出邏輯行的邊界,除非句法支持 NEWLINE (例如,復(fù)合語句中的多行子語句)。根據(jù)顯式或隱式 行拼接 規(guī)則,一個(gè)或多個(gè) 物理行 可組成邏輯行。

2.1.2. 物理行?

物理行是一序列字符,由行尾序列終止。源文件和字符串可使用任意標(biāo)準(zhǔn)平臺(tái)行終止序列 - Unix ASCII 字符 LF (換行)、 Windows ASCII 字符序列 CR LF (回車換行)、或老式 Macintosh ASCII 字符 CR (回車)。不管在哪個(gè)平臺(tái),這些形式均可等價(jià)使用。輸入結(jié)束也可以用作最終物理行的隱式終止符。

嵌入 Python 時(shí),傳入 Python API 的源碼字符串應(yīng)使用 C 標(biāo)準(zhǔn)慣例換行符(\n,代表 ASCII 字符 LF, 行終止符)。

2.1.3. 注釋?

注釋以井號(hào) (#) 開頭,在物理行末尾截止。注意,井號(hào)不是字符串字面值。除非應(yīng)用隱式行拼接規(guī)則,否則,注釋代表邏輯行結(jié)束。句法不解析注釋。

2.1.4. 編碼聲明?

Python 腳本第一或第二行的注釋匹配正則表達(dá)式 coding[=:]\s*([-\w.]+) 時(shí),該注釋會(huì)被當(dāng)作編碼聲明;這個(gè)表達(dá)式的第一組指定了源碼文件的編碼。編碼聲明必須獨(dú)占一行,在第二行時(shí),則第一行必須也是注釋。編碼表達(dá)式的形式如下:

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

這也是 GNU Emacs 認(rèn)可的形式,此外,還支持如下形式:

# vim:fileencoding=<encoding-name>

這是 Bram Moolenaar 的 VIM 認(rèn)可的形式。

沒有編碼聲明時(shí),默認(rèn)編碼為 UTF-8。此外,如果文件的首字節(jié)為 UTF-8 字節(jié)順序標(biāo)志(b'\xef\xbb\xbf'),文件編碼也聲明為 UTF-8(這是 Microsoft 的 notepad 等軟件支持的形式)。

If an encoding is declared, the encoding name must be recognized by Python (see 標(biāo)準(zhǔn)編碼). The encoding is used for all lexical analysis, including string literals, comments and identifiers.

2.1.5. 顯式拼接行?

兩個(gè)及兩個(gè)以上的物理行可用反斜杠(\)拼接為一個(gè)邏輯行,規(guī)則如下:以不在字符串或注釋內(nèi)的反斜杠結(jié)尾時(shí),物理行將與下一行拼接成一個(gè)邏輯行,并刪除反斜杠及其后的換行符。例如:

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

以反斜杠結(jié)尾的行,不能加注釋;反斜杠也不能拼接注釋。除字符串字面值外,反斜杠不能拼接形符(如,除字符串字面值外,不能用反斜杠把形符切分至兩個(gè)物理行)。反斜杠只能在代碼的字符串字面值里,在其他任何位置都是非法的。

2.1.6. 隱式拼接行?

圓括號(hào)、方括號(hào)、花括號(hào)內(nèi)的表達(dá)式可以分成多個(gè)物理行,不必使用反斜杠。例如:

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

隱式行拼接可含注釋;后續(xù)行的縮進(jìn)并不重要;還支持空的后續(xù)行。隱式拼接行之間沒有 NEWLINE 形符。三引號(hào)字符串支持隱式拼接行(見下文),但不支持注釋。

2.1.7. 空白行?

只包含空格符、制表符、換頁符、注釋的邏輯行會(huì)被忽略(即不生成 NEWLINE 形符)。交互模式輸入語句時(shí),空白行的處理方式可能因讀取 - 求值 - 打印循環(huán)(REPL)的具體實(shí)現(xiàn)方式而不同。標(biāo)準(zhǔn)交互模式解釋器中,完全空白的邏輯行(即連空格或注釋都沒有)將結(jié)束多行復(fù)合語句。

2.1.8. 縮進(jìn)?

邏輯行開頭的空白符(空格符和制表符)用于計(jì)算該行的縮進(jìn)層級(jí),決定語句組塊。

制表符(從左至右)被替換為一至八個(gè)空格,縮進(jìn)空格的總數(shù)是八的倍數(shù)(與 Unix 的規(guī)則保持一致)。首個(gè)非空字符前的空格數(shù)決定了該行的縮進(jìn)層次??s進(jìn)不能用反斜杠進(jìn)行多行拼接;首個(gè)反斜杠之前的空白符決定了縮進(jìn)的層次。

源文件混用制表符和空格符縮進(jìn)時(shí),因空格數(shù)量與制表符相關(guān),由此產(chǎn)生的不一致將導(dǎo)致不能正常識(shí)別縮進(jìn)層次,從而觸發(fā) TabError。

跨平臺(tái)兼容性說明: 鑒于非 UNIX 平臺(tái)文本編輯器本身的特性,請(qǐng)勿在源文件中混用制表符和空格符。另外也請(qǐng)注意,不同平臺(tái)有可能會(huì)顯式限制最大縮進(jìn)層級(jí)。

行首含換頁符時(shí),縮進(jìn)計(jì)算將忽略該換頁符。換頁符在行首空白符內(nèi)其他位置的效果未定義(例如,可能導(dǎo)致空格計(jì)數(shù)重置為零)。

連續(xù)行的縮進(jìn)層級(jí)以堆棧形式生成 INDENT 和 DEDENT 形符,說明如下。

讀取文件第一行前,先向棧推入一個(gè)零值,該零值不會(huì)被移除。推入棧的層級(jí)值從底至頂持續(xù)增加。每個(gè)邏輯行開頭的行縮進(jìn)層級(jí)將與棧頂行比較。如果相等,則不做處理。如果新行層級(jí)較高,則會(huì)被推入棧頂,并生成一個(gè) INDENT 形符。如果新行層級(jí)較低,則 應(yīng)當(dāng) 是棧中的層級(jí)數(shù)值之一;棧中高于該層級(jí)的所有數(shù)值都將被移除,每移除一級(jí)數(shù)值生成一個(gè) DEDENT 形符。文件末尾,棧中剩余的每個(gè)大于零的數(shù)值生成一個(gè) DEDENT 形符。

下面的 Python 代碼縮進(jìn)示例雖然正確,但含混不清:

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

下例展示了多種縮進(jìn)錯(cuò)誤:

 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

(實(shí)際上,解析器可以識(shí)別前三個(gè)錯(cuò)誤;只有最后一個(gè)錯(cuò)誤由詞法分析器識(shí)別 --- return r 的縮進(jìn)無法匹配從棧里移除的縮進(jìn)層級(jí)。)

2.1.9. 形符間的空白字符?

除非在邏輯行開頭或字符串內(nèi),空格符、制表符、換頁符等空白符都可以分隔形符。要把兩個(gè)相連形符解讀為不同形符,需要用空白符分隔(例如,ab 是一個(gè)形符,a b 則是兩個(gè)形符)。

2.2. 其他形符?

除 NEWLINE、INDENT、DEDENT 外,還有 標(biāo)識(shí)符、關(guān)鍵字、字面值、運(yùn)算符分隔符 等形符。 空白符(前述的行終止符除外)不是形符,可用于分隔形符。存在二義性時(shí),將從左至右,讀取盡量長的字符串組成合法形符。

2.3. 標(biāo)識(shí)符和關(guān)鍵字?

標(biāo)識(shí)符(也稱為 名稱)的詞法定義說明如下。

Python 標(biāo)識(shí)符的句法基于 Unicode 標(biāo)準(zhǔn)附件 UAX-31,并加入了下文定義的細(xì)化與修改;詳見 PEP 3131 。

與 Python 2.x 一樣,在 ASCII 范圍內(nèi)(U+0001..U+007F),有效標(biāo)識(shí)符字符為: 大小寫字母 AZ、下劃線 _ 、數(shù)字 09,但不能以數(shù)字開頭。

Python 3.0 引入了 ASCII 之外的更多字符(請(qǐng)參閱 PEP 3131)。這些字符的分類使用 unicodedata 模塊中的 Unicode 字符數(shù)據(jù)庫版本。

標(biāo)識(shí)符的長度沒有限制,但區(qū)分大小寫。

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 - 字母數(shù)字

  • Mn - 非空白標(biāo)識(shí)

  • Mc - 含空白標(biāo)識(shí)

  • Nd - 十進(jìn)制數(shù)字

  • Pc - 連接標(biāo)點(diǎn)

  • Other_ID_Start - explicit list of characters in PropList.txt to support backwards compatibility

  • Other_ID_Continue - 同上

在解析時(shí),所有標(biāo)識(shí)符都會(huì)被轉(zhuǎn)換為規(guī)范形式 NFKC;標(biāo)識(shí)符的比較都是基于 NFKC。

A non-normative HTML file listing all valid identifier characters for Unicode 14.0.0 can be found at https://www.unicode.org/Public/14.0.0/ucd/DerivedCoreProperties.txt

2.3.1. 關(guān)鍵字?

以下標(biāo)識(shí)符為保留字,或稱 關(guān)鍵字,不可用于普通標(biāo)識(shí)符。關(guān)鍵字的拼寫必須與這里列出的完全一致:

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. 軟關(guān)鍵字?

3.10 新版功能.

某些標(biāo)識(shí)符僅在特定上下文中被保留。 它們被稱為 軟關(guān)鍵字match, case_ 等標(biāo)識(shí)符在模式匹配語句相關(guān)的上下文中具有相當(dāng)于關(guān)鍵字的語義,但這種區(qū)分是在解析器層級(jí)完成,而不是在形符化的時(shí)候。

作為軟關(guān)鍵字,它們能夠與模式匹配一起使用,同時(shí)仍然保持與使用 match, case_ 作為標(biāo)識(shí)符名稱的現(xiàn)有代碼的兼容性。

2.3.3. 保留的標(biāo)識(shí)符類?

某些標(biāo)識(shí)符類(除了關(guān)鍵字)具有特殊含義。這些類的命名模式以下劃線字符開頭,并以下劃線結(jié)尾:

_*

Not imported by from module import *.

_

In a case pattern within a match statement, _ is a soft keyword that denotes a wildcard.

Separately, the interactive interpreter makes the result of the last evaluation available in the variable _. (It is stored in the builtins module, alongside built-in functions like print.)

Elsewhere, _ is a regular identifier. It is often used to name "special" items, but it is not special to Python itself.

備注

_ 常用于連接國際化文本;詳見 gettext 模塊文檔。

It is also commonly used for unused variables.

__*__

系統(tǒng)定義的名稱,通常簡稱為 "dunder" 。這些名稱由解釋器及其實(shí)現(xiàn)(包括標(biāo)準(zhǔn)庫)定義?,F(xiàn)有系統(tǒng)定義名稱相關(guān)的論述詳見 特殊方法名稱 等章節(jié)。Python 未來版本中還將定義更多此類名稱。任何情況下,任何 不顯式遵從 __*__ 名稱的文檔用法,都可能導(dǎo)致無警告提示的錯(cuò)誤。

__*

類的私有名稱。類定義時(shí),此類名稱以一種混合形式重寫,以避免基類及派生類的 "私有" 屬性之間產(chǎn)生名稱沖突。詳見 標(biāo)識(shí)符(名稱)。

2.4. 字面值?

字面值是內(nèi)置類型常量值的表示法。

2.4.1. 字符串與字節(jié)串字面值?

字符串字面值的詞法定義如下:

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>

One syntactic restriction not indicated by these productions is that whitespace is not allowed between the stringprefix or bytesprefix and the rest of the literal. The source character set is defined by the encoding declaration; it is UTF-8 if no encoding declaration is given in the source file; see section 編碼聲明.

In plain English: Both types of literals can be enclosed in matching single quotes (') or double quotes ("). They can also be enclosed in matching groups of three single or double quotes (these are generally referred to as triple-quoted strings). The backslash (\) character is used to give special meaning to otherwise ordinary characters like n, which means 'newline' when escaped (\n). It can also be used to escape characters that otherwise have a special meaning, such as newline, backslash itself, or the quote character. See escape sequences below for examples.

字節(jié)串字面值要加前綴 'b''B';生成的是類型 bytes 的實(shí)例,不是類型 str 的實(shí)例;字節(jié)串只能包含 ASCII 字符;字節(jié)串?dāng)?shù)值大于等于 128 時(shí),必須用轉(zhuǎn)義表示。

字符串和字節(jié)串都可以加前綴 'r''R',稱為 原始字符串,原始字符串把反斜杠當(dāng)作原義字符,不執(zhí)行轉(zhuǎn)義操作。因此,原始字符串不轉(zhuǎn)義 '\U''\u'。與 Python 2.x 的原始 unicode 字面值操作不同,Python 3.x 現(xiàn)已不支持 'ur' 句法。

3.3 新版功能: 新增原始字節(jié)串 'rb' 前綴,是 'br' 的同義詞。

3.3 新版功能: 支持 unicode 字面值(u'value')遺留代碼,簡化 Python 2.x 和 3.x 并行代碼庫的維護(hù)工作。詳見 PEP 414。

前綴為 'f''F' 的字符串稱為 格式字符串;詳見 格式字符串字面值'f' 可與 'r' 連用,但不能與 'b''u' 連用,因此,可以使用原始格式字符串,但不能使用格式字節(jié)串字面值。

三引號(hào)字面值可以包含未轉(zhuǎn)義的換行和引號(hào)(原樣保留),除了連在一起的,用于終止字面值的,未經(jīng)轉(zhuǎn)義的三個(gè)引號(hào)。("引號(hào)" 是啟用字面值的字符,可以是 ',也可以是 "。)

如未標(biāo)注 'r''R' 前綴,字符串和字節(jié)串字面值中,轉(zhuǎn)義序列以類似 C 標(biāo)準(zhǔn)的規(guī)則進(jìn)行解釋??捎玫霓D(zhuǎn)義序列如下:

轉(zhuǎn)義序列

含意

備注

\newline

忽略反斜杠與換行符

\\

反斜杠(\

\'

單引號(hào)('

\"

雙引號(hào)("

\a

ASCII 響鈴(BEL)

\b

ASCII 退格符(BS)

\f

ASCII 換頁符(FF)

\n

ASCII 換行符(LF)

\r

ASCII 回車符(CR)

\t

ASCII 水平制表符(TAB)

\v

ASCII 垂直制表符(VT)

\ooo

八進(jìn)制數(shù) ooo 字符

(1,3)

\xhh

十六進(jìn)制數(shù) hh 字符

(2,3)

字符串字面值專用的轉(zhuǎn)義序列:

轉(zhuǎn)義序列

含意

備注

\N{name}

Unicode 數(shù)據(jù)庫中名為 name 的字符

(4)

\uxxxx

16 位十六進(jìn)制數(shù) xxxx 碼位的字符

(5)

\Uxxxxxxxx

32 位 16 進(jìn)制數(shù) xxxxxxxx 碼位的字符

(6)

注釋:

  1. 與 C 標(biāo)準(zhǔn)一致,接受最多三個(gè)八進(jìn)制數(shù)字。

    在 3.11 版更改: Octal escapes with value larger than 0o377 produce a DeprecationWarning. In a future Python version they will be a SyntaxWarning and eventually a SyntaxError.

  2. 與 C 標(biāo)準(zhǔn)不同,必須為兩個(gè)十六進(jìn)制數(shù)字。

  3. 字節(jié)串 字面值中,十六進(jìn)制數(shù)和八進(jìn)制數(shù)的轉(zhuǎn)義碼以相應(yīng)數(shù)值代表每個(gè)字節(jié)。字符串 字面值中,這些轉(zhuǎn)義碼以相應(yīng)數(shù)值代表每個(gè) Unicode 字符。

  4. 在 3.3 版更改: 加入了對(duì)別名 1 的支持。

  5. 必須為 4 個(gè)十六進(jìn)制數(shù)碼。

  6. 表示任意 Unicode 字符。必須為 8 個(gè)十六進(jìn)制數(shù)碼。

與 C 標(biāo)準(zhǔn)不同,無法識(shí)別的轉(zhuǎn)義序列在字符串里原樣保留,即,輸出結(jié)果保留反斜杠。(調(diào)試時(shí),這種方式很有用:輸錯(cuò)轉(zhuǎn)義序列時(shí),更容易在輸出結(jié)果中識(shí)別錯(cuò)誤。)注意,在字節(jié)串字面值內(nèi),字符串字面值專用的轉(zhuǎn)義序列屬于無法識(shí)別的轉(zhuǎn)義序列。

在 3.6 版更改: 無法識(shí)別的轉(zhuǎn)義序列觸發(fā) DeprecationWarning。未來的 Python 發(fā)行版將改為觸發(fā) SyntaxWarning,最終會(huì)改為觸發(fā) SyntaxError。

即使在原始字面值中,引號(hào)也可以用反斜杠轉(zhuǎn)義,但反斜杠會(huì)保留在輸出結(jié)果里;例如 r"\"" 是由兩個(gè)字符組成的有效字符串字面值:反斜杠和雙引號(hào);r"\" 則不是有效字符串字面值(原始字符串也不能以奇數(shù)個(gè)反斜杠結(jié)尾)。尤其是,原始字面值不能以單個(gè)反斜杠結(jié)尾 (反斜杠會(huì)轉(zhuǎn)義其后的引號(hào))。還要注意,反斜杠加換行在字面值中被解釋為兩個(gè)字符,而 不是 連續(xù)行。

2.4.2. 字符串字面值合并?

以空白符分隔的多個(gè)相鄰字符串或字節(jié)串字面值,可用不同引號(hào)標(biāo)注,等同于合并操作。因此,"hello" 'world' 等價(jià)于 "helloworld"。此功能不需要反斜杠,即可將長字符串分為多個(gè)物理行,還可以為不同部分的字符串添加注釋,例如:

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

注意,此功能在句法層面定義,在編譯時(shí)實(shí)現(xiàn)。在運(yùn)行時(shí),合并字符串表達(dá)式必須使用 '+' 運(yùn)算符。還要注意,字面值合并可以為每個(gè)部分應(yīng)用不同的引號(hào)風(fēng)格(甚至混用原始字符串和三引號(hào)字符串),格式字符串字面值也可以與純字符串字面值合并。

2.4.3. 格式字符串字面值?

3.6 新版功能.

格式字符串字面值 或稱 f-string 是標(biāo)注了 'f''F' 前綴的字符串字面值。這種字符串可包含替換字段,即以 {} 標(biāo)注的表達(dá)式。其他字符串字面值只是常量,格式字符串字面值則是可在運(yùn)行時(shí)求值的表達(dá)式。

除非字面值標(biāo)記為原始字符串,否則,與在普通字符串字面值中一樣,轉(zhuǎn)義序列也會(huì)被解碼。解碼后,用于字符串內(nèi)容的語法如下:

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>

雙花括號(hào) '{{''}}' 被替換為單花括號(hào),花括號(hào)外的字符串仍按字面值處理。單左花括號(hào) '{' 標(biāo)記以 Python 表達(dá)式開頭的替換字段。在表達(dá)式后加等于號(hào) '=',可在求值后,同時(shí)顯示表達(dá)式文本及其結(jié)果(用于調(diào)試)。 隨后是用嘆號(hào) '!' 標(biāo)記的轉(zhuǎn)換字段。還可以在冒號(hào) ':' 后附加格式說明符。替換字段以右花括號(hào) '}' 為結(jié)尾。

格式字符串字面值中,表達(dá)式的處理與圓括號(hào)中的常規(guī) Python 表達(dá)式基本一樣,但也有一些不同的地方。不允許使用空表達(dá)式;lambda 和賦值表達(dá)式 := 必須顯式用圓括號(hào)標(biāo)注;替換表達(dá)式可以包含換行(例如,三引號(hào)字符串中),但不能包含注釋;在格式字符串字面值語境內(nèi),按從左至右的順序,為每個(gè)表達(dá)式求值。

在 3.7 版更改: Python 3.7 以前, 因?yàn)閷?shí)現(xiàn)的問題,不允許在格式字符串字面值表達(dá)式中使用 await 表達(dá)式與包含 async for 子句的推導(dǎo)式。

表達(dá)式里含等號(hào) '=' 時(shí),輸出內(nèi)容包括表達(dá)式文本、'=' 、求值結(jié)果。輸出內(nèi)容可以保留表達(dá)式中左花括號(hào) '{' 后,及 '=' 后的空格。沒有指定格式時(shí),'=' 默認(rèn)調(diào)用表達(dá)式的 repr()。指定了格式時(shí),默認(rèn)調(diào)用表達(dá)式的 str(),除非聲明了轉(zhuǎn)換字段 '!r'

3.8 新版功能: 等號(hào) '='。

指定了轉(zhuǎn)換符時(shí),表達(dá)式求值的結(jié)果會(huì)先轉(zhuǎn)換,再格式化。轉(zhuǎn)換符 '!s' 調(diào)用 str() 轉(zhuǎn)換求值結(jié)果,'!r' 調(diào)用 repr()'!a' 調(diào)用 ascii()。

輸出結(jié)果的格式化使用 format() 協(xié)議。格式說明符傳入表達(dá)式或轉(zhuǎn)換結(jié)果的 __format__() 方法。省略格式說明符,則傳入空字符串。然后,格式化結(jié)果包含在整個(gè)字符串的最終值里。

頂層格式說明符可以包含嵌套替換字段。嵌套字段也可以包含自己的轉(zhuǎn)換字段和 格式說明符,但不可再包含更深層嵌套的替換字段。格式說明符微語言str.format() 方法使用的微語言相同。

格式化字符串字面值可以拼接,但是一個(gè)替換字段不能拆分到多個(gè)字面值。

格式字符串字面值示例如下:

>>>
>>> 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" '

與常規(guī)字符串字面值的語法一樣,替換字段中的字符不能與外層格式字符串字面值的引號(hào)沖突:

f"abc {a["x"]} def"    # error: outer string literal ended prematurely
f"abc {a['x']} def"    # workaround: use different quoting

格式表達(dá)式中不能有反斜杠,否則會(huì)報(bào)錯(cuò):

f"newline: {ord('\n')}"  # raises SyntaxError

要使用反斜杠轉(zhuǎn)義的值,則需創(chuàng)建臨時(shí)變量。

>>>
>>> newline = ord('\n')
>>> f"newline: {newline}"
'newline: 10'

即便未包含表達(dá)式,格式字符串字面值也不能用作文檔字符串。

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

參閱 PEP 498,了解格式字符串字面值的提案,以及與格式字符串機(jī)制相關(guān)的 str.format()。

2.4.4. 數(shù)值字面值?

數(shù)值字面值有三種類型:整數(shù)、浮點(diǎn)數(shù)、虛數(shù)。沒有復(fù)數(shù)字面值(復(fù)數(shù)由實(shí)數(shù)加虛數(shù)構(gòu)成)。

注意,數(shù)值字面值不含正負(fù)號(hào);實(shí)際上,-1 等負(fù)數(shù)是由一元運(yùn)算符 '-' 和字面值 1 合成的。

2.4.5. 整數(shù)字面值?

整數(shù)字面值詞法定義如下:

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"

整數(shù)字面值的長度沒有限制,能一直大到占滿可用內(nèi)存。

確定數(shù)值時(shí),會(huì)忽略字面值中的下劃線。下劃線只是為了分組數(shù)字,讓數(shù)字更易讀。下劃線可在數(shù)字之間,也可在 0x 等基數(shù)說明符后。

注意,除了 0 以外,十進(jìn)制數(shù)字的開頭不允許有零。以免與 Python 3.0 版之前使用的 C 樣式八進(jìn)制字面值混淆。

整數(shù)字面值示例如下:

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

在 3.6 版更改: 現(xiàn)已支持在字面值中,用下劃線分組數(shù)字。

2.4.6. 浮點(diǎn)數(shù)字面值?

浮點(diǎn)數(shù)字面值詞法定義如下:

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

注意,解析時(shí),整數(shù)和指數(shù)部分總以 10 為基數(shù)。例如,077e010 是合法的,表示的數(shù)值與 77e10 相同。浮點(diǎn)數(shù)字面值的支持范圍取決于具體實(shí)現(xiàn)。整數(shù)字面值支持用下劃線分組數(shù)字。

浮點(diǎn)數(shù)字面值示例如下:

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

在 3.6 版更改: 現(xiàn)已支持在字面值中,用下劃線分組數(shù)字。

2.4.7. 虛數(shù)字面值?

虛數(shù)字面值詞法定義如下:

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

虛數(shù)字面值生成實(shí)部為 0.0 的復(fù)數(shù)。復(fù)數(shù)由一對(duì)浮點(diǎn)數(shù)表示,它們的取值范圍相同。創(chuàng)建實(shí)部不為零的復(fù)數(shù),則需添加浮點(diǎn)數(shù),例如 (3+4j)。虛數(shù)字面值示例如下:

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

2.5. 運(yùn)算符?

運(yùn)算符如下所示:

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

2.6. 分隔符?

以下形符在語法中為分隔符:

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

句點(diǎn)也可以用于浮點(diǎn)數(shù)和虛數(shù)字面值。三個(gè)連續(xù)句點(diǎn)表示省略符。列表后半部分是增強(qiáng)賦值操作符,用作詞法分隔符,但也可以執(zhí)行運(yùn)算。

以下 ASCII 字符具有特殊含義,對(duì)詞法分析器有重要意義:

'       "       #       \

以下 ASCII 字符不用于 Python。在字符串字面值或注釋外使用時(shí),將直接報(bào)錯(cuò):

$       ?       `

備注

1

https://www.unicode.org/Public/11.0.0/ucd/NameAliases.txt