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

Python 將讀取的程序文本轉(zhuǎn)為 Unicode 代碼點(diǎn);編碼聲明用于指定源文件的編碼,默認(rèn)為 UTF-8,詳見(jiàn) PEP 3120。源文件不能解碼時(shí),觸發(fā) SyntaxError。
2.1. 行結(jié)構(gòu)
Python 程序可以拆分為多個(gè) 邏輯行。
2.1.1. 邏輯行
NEWLINE 形符表示結(jié)束邏輯行。語(yǔ)句不能超出邏輯行的邊界,除非句法支持 NEWLINE (例如,復(fù)合語(yǔ)句中的多行子語(yǔ)句)。根據(jù)顯式或隱式 行拼接 規(guī)則,一個(gè)或多個(gè) 物理行 可組成邏輯行。
2.1.2. 物理行
物理行是一序列字符,由行尾序列終止。源文件和字符串可使用任意標(biāo)準(zhǔn)平臺(tái)行終止序列 - Unix ASCII 字符 LF (換行)、 Windows ASCII 字符序列 CR LF (回車(chē)換行)、或老式 Macintosh ASCII 字符 CR (回車(chē))。不管在哪個(gè)平臺(tái),這些形式均可等價(jià)使用。輸入結(jié)束也可以用作最終物理行的隱式終止符。
嵌入 Python 時(shí),傳入 Python API 的源碼字符串應(yīng)使用 C 標(biāo)準(zhǔn)慣例換行符(\n,代表 ASCII 字符 LF, 行終止符)。
2.1.3. 注釋
注釋以井號(hào) (#) 開(kāi)頭,在物理行末尾截止。注意,井號(hào)不是字符串字面值。除非應(yīng)用隱式行拼接規(guī)則,否則,注釋代表邏輯行結(jié)束。句法不解析注釋。
2.1.4. 編碼聲明
Python 腳本第一或第二行的注釋匹配正則表達(dá)式 coding[=:]\s*([-\w.]+) 時(shí),該注釋會(huì)被當(dāng)作編碼聲明;這個(gè)表達(dá)式的第一組指定了源碼文件的編碼。編碼聲明必須獨(dú)占一行,在第二行時(shí),則第一行必須也是注釋。編碼表達(dá)式的形式如下:
# -*- coding:-*-
這也是 GNU Emacs 認(rèn)可的形式,此外,還支持如下形式:
# vim:fileencoding=
這是 Bram Moolenaar 的 VIM 認(rèn)可的形式。
沒(méi)有編碼聲明時(shí),默認(rèn)編碼為 UTF-8。此外,如果文件的首字節(jié)為 UTF-8 字節(jié)順序標(biāo)志(b'\xef\xbb\xbf'),文件編碼也聲明為 UTF-8(這是 Microsoft 的 notepad 等軟件支持的形式)。
如果聲明了編碼格式,該編碼格式的名稱(chēng)必須是 Python 可識(shí)別的 (參見(jiàn) 標(biāo)準(zhǔn)編碼)。 編碼格式會(huì)被用于所有的詞法分析,包括字符串字面值、注釋和標(biāo)識(shí)符等。
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 datereturn 1
以反斜杠結(jié)尾的行,不能加注釋?zhuān)环葱备芤膊荒芷唇幼⑨?。除字符串字面值外,反斜杠不能拼接形符(如,除字符串字面值外,不能用反斜杠把形符切分至兩個(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
隱式行拼接可含注釋?zhuān)缓罄m(xù)行的縮進(jìn)并不重要;還支持空的后續(xù)行。隱式拼接行之間沒(méi)有 NEWLINE 形符。三引號(hào)字符串支持隱式拼接行(見(jiàn)下文),但不支持注釋。
2.1.7. 空白行
只包含空格符、制表符、換頁(yè)符、注釋的邏輯行會(huì)被忽略(即不生成 NEWLINE 形符)。交互模式輸入語(yǔ)句時(shí),空白行的處理方式可能因讀取 - 求值 - 打印循環(huán)(REPL)的具體實(shí)現(xiàn)方式而不同。標(biāo)準(zhǔn)交互模式解釋器中,完全空白的邏輯行(即連空格或注釋都沒(méi)有)將結(jié)束多行復(fù)合語(yǔ)句。
2.1.8. 縮進(jìn)
邏輯行開(kāi)頭的空白符(空格符和制表符)用于計(jì)算該行的縮進(jìn)層級(jí),決定語(yǔ)句組塊。
制表符(從左至右)被替換為一至八個(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)兼容性說(shuō)明: 鑒于非 UNIX 平臺(tái)文本編輯器本身的特性,請(qǐng)勿在源文件中混用制表符和空格符。另外也請(qǐng)注意,不同平臺(tái)有可能會(huì)顯式限制最大縮進(jìn)層級(jí)。
行首含換頁(yè)符時(shí),縮進(jìn)計(jì)算將忽略該換頁(yè)符。換頁(yè)符在行首空白符內(nèi)其他位置的效果未定義(例如,可能導(dǎo)致空格計(jì)數(shù)重置為零)。
連續(xù)行的縮進(jìn)層級(jí)以堆棧形式生成 INDENT 和 DEDENT 形符,說(shuō)明如下。
讀取文件第一行前,先向棧推入一個(gè)零值,該零值不會(huì)被移除。推入棧的層級(jí)值從底至頂持續(xù)增加。每個(gè)邏輯行開(kāi)頭的行縮進(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 lif 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 indentedfor i in range(len(l)): # error: not indenteds = l[:i] + l[i+1:]p = perm(l[:i] + l[i+1:]) # error: unexpected indentfor 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)無(wú)法匹配從棧里移除的縮進(jìn)層級(jí)。)
2.1.9. 形符間的空白字符
除非在邏輯行開(kāi)頭或字符串內(nèi),空格符、制表符、換頁(yè)符等空白符都可以分隔形符。要把兩個(gè)相連形符解讀為不同形符,需要用空白符分隔(例如,ab 是一個(gè)形符,a b 則是兩個(gè)形符)。
2.2. 其他形符
除 NEWLINE、INDENT、DEDENT 外,還有 標(biāo)識(shí)符、關(guān)鍵字、字面值、運(yùn)算符 、分隔符 等形符。 空白符(前述的行終止符除外)不是形符,可用于分隔形符。存在二義性時(shí),將從左至右,讀取盡量長(zhǎng)的字符串組成合法形符。
2.3. 標(biāo)識(shí)符和關(guān)鍵字
標(biāo)識(shí)符(也稱(chēng)為 名稱(chēng))的詞法定義說(shuō)明如下。
Python 標(biāo)識(shí)符的句法基于 Unicode 標(biāo)準(zhǔn)附件 UAX-31,并加入了下文定義的細(xì)化與修改;詳見(jiàn) PEP 3131 。
與 Python 2.x 一樣,在 ASCII 范圍內(nèi)(U+0001..U+007F),有效標(biāo)識(shí)符字符為: 大小寫(xiě)字母 A 至 Z、下劃線(xiàn) _ 、數(shù)字 0 至 9,但不能以數(shù)字開(kāi)頭。
Python 3.0 引入了 ASCII 之外的更多字符(請(qǐng)參閱 PEP 3131)。這些字符的分類(lèi)使用 unicodedata 模塊中的 Unicode 字符數(shù)據(jù)庫(kù)版本。
標(biāo)識(shí)符的長(zhǎng)度沒(méi)有限制,但區(qū)分大小寫(xiě)。
- identifier ::= xid_start xid_continue*
- id_start ::=
- id_continue ::=
- xid_start ::=
- xid_continue ::=
上述 Unicode 類(lèi)別碼的含義:
-
Lu - 大寫(xiě)字母
-
Ll - 小寫(xiě)字母
-
Lt - 詞首大寫(xiě)字母
-
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í)符為保留字,或稱(chēng) 關(guān)鍵字,不可用于普通標(biāo)識(shí)符。關(guān)鍵字的拼寫(xiě)必須與這里列出的完全一致:
False await else import passNone break except in raiseTrue class finally is returnand continue for lambda tryas def from nonlocal whileassert del global not withasync elif if or yield
2.3.2. 軟關(guān)鍵字
3.10 新版功能.
某些標(biāo)識(shí)符僅在特定上下文中被保留。 它們被稱(chēng)為 軟關(guān)鍵字。 match, case 和 _ 等標(biāo)識(shí)符在模式匹配語(yǔ)句相關(guān)的上下文中具有相當(dāng)于關(guān)鍵字的語(yǔ)義,但這種區(qū)分是在解析器層級(jí)完成,而不是在形符化的時(shí)候。
作為軟關(guān)鍵字,它們能夠與模式匹配一起使用,同時(shí)仍然保持與使用 match, case 和 _ 作為標(biāo)識(shí)符名稱(chēng)的現(xiàn)有代碼的兼容性。
2.3.3. 保留的標(biāo)識(shí)符類(lèi)
某些標(biāo)識(shí)符類(lèi)(除了關(guān)鍵字)具有特殊含義。這些類(lèi)的命名模式以下劃線(xiàn)字符開(kāi)頭,并以下劃線(xiàn)結(jié)尾:
_*
不會(huì)被 from module import * 所導(dǎo)入。
_
在 match 語(yǔ)句內(nèi)部的 case 模式中,_ 是一個(gè) 軟關(guān)鍵字,它表示 通配符。
在此之外,交互式解釋器會(huì)將最后一次求值的結(jié)果放到變量 _ 中。 (它與 print 等內(nèi)置函數(shù)一起被存儲(chǔ)于 builtins 模塊。)
在其他地方,_ 是一個(gè)常規(guī)標(biāo)識(shí)符。 它常常被用來(lái)命名 “特殊” 條目,但對(duì) Python 本身來(lái)說(shuō)毫無(wú)特殊之處。
備注
_ 常用于連接國(guó)際化文本;詳見(jiàn) gettext 模塊文檔。
它還經(jīng)常被用來(lái)命名無(wú)需使用的變量。
__*__
系統(tǒng)定義的名稱(chēng),通常簡(jiǎn)稱(chēng)為 “dunder” 。這些名稱(chēng)由解釋器及其實(shí)現(xiàn)(包括標(biāo)準(zhǔn)庫(kù))定義?,F(xiàn)有系統(tǒng)定義名稱(chēng)相關(guān)的論述詳見(jiàn) 特殊方法名稱(chēng) 等章節(jié)。Python 未來(lái)版本中還將定義更多此類(lèi)名稱(chēng)。任何情況下,任何 不顯式遵從 __*__ 名稱(chēng)的文檔用法,都可能導(dǎo)致無(wú)警告提示的錯(cuò)誤。
__*
類(lèi)的私有名稱(chēng)。類(lèi)定義時(shí),此類(lèi)名稱(chēng)以一種混合形式重寫(xiě),以避免基類(lèi)及派生類(lèi)的 “私有” 屬性之間產(chǎn)生名稱(chēng)沖突。詳見(jiàn) 標(biāo)識(shí)符(名稱(chēng))。
2.4. 字面值
字面值是內(nèi)置類(lè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 ::=
- longstringchar ::=
- stringescapeseq ::= "\"
- 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 ::=
- longbyteschar ::=
- bytesescapeseq ::= "\"
這些產(chǎn)生式未指明的一個(gè)句法限制是空白符不允許在 stringprefix 或 bytesprefix 與字面值的其余部分之間出現(xiàn)。 源字符集是由編碼格式聲明來(lái)定義的;如果源文件沒(méi)有給出編碼格式聲明則默認(rèn) UTF-8;參見(jiàn) 編碼聲明 一節(jié)。
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 escape characters that otherwise have a special meaning, such as newline, backslash itself, or the quote character.
字節(jié)串字面值要加前綴 'b' 或 'B';生成的是類(lèi)型 bytes 的實(shí)例,不是類(lèi)型 str 的實(shí)例;字節(jié)串只能包含 ASCII 字符;字節(jié)串?dāng)?shù)值大于等于 128 時(shí),必須用轉(zhuǎn)義表示。
字符串和字節(jié)串都可以加前綴 'r' 或 'R',稱(chēng)為 原始字符串,原始字符串把反斜杠當(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')遺留代碼,簡(jiǎn)化 Python 2.x 和 3.x 并行代碼庫(kù)的維護(hù)工作。詳見(jiàn) PEP 414。
前綴為 'f' 或 'F' 的字符串稱(chēng)為 格式字符串;詳見(jiàn) 格式字符串字面值。'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)義序列以類(lèi)似 C 標(biāo)準(zhǔn)的規(guī)則進(jìn)行解釋??捎玫霓D(zhuǎn)義序列如下:
|
轉(zhuǎn)義序列 |
含意 |
備注 |
|---|---|---|
|
忽略反斜杠與換行符 |
(1) |
|
反斜杠( |
|
|
單引號(hào)( |
|
|
雙引號(hào)( |
|
|
ASCII 響鈴(BEL) |
|
|
ASCII 退格符(BS) |
|
|
ASCII 換頁(yè)符(FF) |
|
|
ASCII 換行符(LF) |
|
|
ASCII 回車(chē)符(CR) |
|
|
ASCII 水平制表符(TAB) |
|
|
ASCII 垂直制表符(VT) |
|
|
八進(jìn)制數(shù) ooo 字符 |
(2,4) |
|
十六進(jìn)制數(shù) hh 字符 |
(3,4) |
字符串字面值專(zhuān)用的轉(zhuǎn)義序列:
|
轉(zhuǎn)義序列 |
含意 |
備注 |
|---|---|---|
|
Unicode 數(shù)據(jù)庫(kù)中名為 name 的字符 |
(5) |
|
16 位十六進(jìn)制數(shù) xxxx 碼位的字符 |
(6) |
|
32 位 16 進(jìn)制數(shù) xxxxxxxx 碼位的字符 |
(7) |
注釋?zhuān)?/p>
-
A backslash can be added at the end of a line to ignore the newline:
>>> 'This string will not include \... backslashes or newline characters.''This string will not include backslashes or newline characters.'
The same result can be achieved using triple-quoted strings, or parentheses and string literal concatenation.
-
與 C 標(biāo)準(zhǔn)一致,接受最多三個(gè)八進(jìn)制數(shù)字。
在 3.11 版更改: Octal escapes with value larger than
0o377produce a DeprecationWarning. In a future Python version they will be a SyntaxWarning and eventually a SyntaxError. -
與 C 標(biāo)準(zhǔn)不同,必須為兩個(gè)十六進(jìn)制數(shù)字。
-
字節(jié)串 字面值中,十六進(jìn)制數(shù)和八進(jìn)制數(shù)的轉(zhuǎn)義碼以相應(yīng)數(shù)值代表每個(gè)字節(jié)。字符串 字面值中,這些轉(zhuǎn)義碼以相應(yīng)數(shù)值代表每個(gè) Unicode 字符。
-
在 3.3 版更改: 加入了對(duì)別名 1 的支持。
-
必須為 4 個(gè)十六進(jìn)制數(shù)碼。
-
表示任意 Unicode 字符。必須為 8 個(gè)十六進(jìn)制數(shù)碼。
與 C 標(biāo)準(zhǔn)不同,無(wú)法識(shí)別的轉(zhuǎn)義序列在字符串里原樣保留,即,輸出結(jié)果保留反斜杠。(調(diào)試時(shí),這種方式很有用:輸錯(cuò)轉(zhuǎn)義序列時(shí),更容易在輸出結(jié)果中識(shí)別錯(cuò)誤。)注意,在字節(jié)串字面值內(nèi),字符串字面值專(zhuān)用的轉(zhuǎn)義序列屬于無(wú)法識(shí)別的轉(zhuǎn)義序列。
在 3.6 版更改: 無(wú)法識(shí)別的轉(zhuǎn)義序列觸發(fā) DeprecationWarning。未來(lái)的 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"。此功能不需要反斜杠,即可將長(zhǎng)字符串分為多個(gè)物理行,還可以為不同部分的字符串添加注釋?zhuān)纾?/p>
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 新版功能.
格式字符串字面值 或稱(chēng) f-string 是標(biāo)注了 'f' 或 'F' 前綴的字符串字面值。這種字符串可包含替換字段,即以 {} 標(biāo)注的表達(dá)式。其他字符串字面值只是常量,格式字符串字面值則是可在運(yùn)行時(shí)求值的表達(dá)式。
除非字面值標(biāo)記為原始字符串,否則,與在普通字符串字面值中一樣,轉(zhuǎn)義序列也會(huì)被解碼。解碼后,用于字符串內(nèi)容的語(yǔ)法如下:
- 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 ::=
雙花括號(hào) '{{' 或 '}}' 被替換為單花括號(hào),花括號(hào)外的字符串仍按字面值處理。單左花括號(hào) '{' 標(biāo)記以 Python 表達(dá)式開(kāi)頭的替換字段。在表達(dá)式后加等于號(hào) '=',可在求值后,同時(shí)顯示表達(dá)式文本及其結(jié)果(用于調(diào)試)。 隨后是用嘆號(hào) '!' 標(biāo)記的轉(zhuǎn)換字段。還可以在冒號(hào) ':' 后附加格式說(shuō)明符。替換字段以右花括號(hào) '}' 為結(jié)尾。
格式字符串字面值中,表達(dá)式的處理與圓括號(hào)中的常規(guī) Python 表達(dá)式基本一樣,但也有一些不同的地方。不允許使用空表達(dá)式;lambda 和賦值表達(dá)式 := 必須顯式用圓括號(hào)標(biāo)注;替換表達(dá)式可以包含換行(例如,三引號(hào)字符串中),但不能包含注釋?zhuān)辉诟袷阶址置嬷嫡Z(yǔ)境內(nèi),按從左至右的順序,為每個(gè)表達(dá)式求值。
在 3.7 版更改: Python 3.7 以前, 因?yàn)閷?shí)現(xiàn)的問(wèn)題,不允許在格式字符串字面值表達(dá)式中使用 await 表達(dá)式與包含 async for 子句的推導(dǎo)式。
表達(dá)式里含等號(hào) '=' 時(shí),輸出內(nèi)容包括表達(dá)式文本、'=' 、求值結(jié)果。輸出內(nèi)容可以保留表達(dá)式中左花括號(hào) '{' 后,及 '=' 后的空格。沒(méi)有指定格式時(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é)議。格式說(shuō)明符傳入表達(dá)式或轉(zhuǎn)換結(jié)果的 __format__() 方法。省略格式說(shuō)明符,則傳入空字符串。然后,格式化結(jié)果包含在整個(gè)字符串的最終值里。
Top-level format specifiers may include nested replacement fields. These nested fields may include their own conversion fields and format specifiers, but may not include more deeply nested replacement fields. The format specifier mini-language is the same as that used by the str.format() method.
格式化字符串字面值可以拼接,但是一個(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ī)字符串字面值的語(yǔ)法一樣,替換字段中的字符不能與外層格式字符串字面值的引號(hào)沖突:
f"abc {a["x"]} def" # error: outer string literal ended prematurelyf"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 NoneTrue
參閱 PEP 498,了解格式字符串字面值的提案,以及與格式字符串機(jī)制相關(guān)的 str.format()。
2.4.4. 數(shù)值字面值
數(shù)值字面值有三種類(lèi)型:整數(shù)、浮點(diǎn)數(shù)、虛數(shù)。沒(méi)有復(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ù)字面值的長(zhǎng)度沒(méi)有限制,能一直大到占滿(mǎn)可用內(nèi)存。
確定數(shù)值時(shí),會(huì)忽略字面值中的下劃線(xiàn)。下劃線(xiàn)只是為了分組數(shù)字,讓數(shù)字更易讀。下劃線(xiàn)可在數(shù)字之間,也可在 0x 等基數(shù)說(shuō)明符后。
注意,除了 0 以外,十進(jìn)制數(shù)字的開(kāi)頭不允許有零。以免與 Python 3.0 版之前使用的 C 樣式八進(jìn)制字面值混淆。
整數(shù)字面值示例如下:
7 2147483647 0o177 0b1001101113 79228162514264337593543950336 0o377 0xdeadbeef100_000_000_000 0b_1110_0101
在 3.6 版更改: 現(xiàn)已支持在字面值中,用下劃線(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ù)字面值支持用下劃線(xiàn)分組數(shù)字。
浮點(diǎn)數(shù)字面值示例如下:
3.14 10. .001 1e100 3.14e-10 0e0 3.14_15_93
在 3.6 版更改: 現(xiàn)已支持在字面值中,用下劃線(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. 分隔符
以下形符在語(yǔ)法中為分隔符:
( ) [ ] { }, : . ; @ = ->+= -= *= /= //= %= @=&= |= ^= >>= <<= **=
句點(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
本文名稱(chēng):創(chuàng)新互聯(lián)Python教程:2.詞法分析
鏈接URL:http://m.fisionsoft.com.cn/article/dhjpdpc.html


咨詢(xún)
建站咨詢(xún)
