Python字面值

字面值是Python内置类型常量值的表示法。字面值可以是数字、字符串、布尔值、列表、元组、字典等内置类型的值。字面值可以直接在代码中使用,而不需要使用变量来存储它们。

一、字符串与字节串字面值

字符串字面值的词法定义如下:

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>

这些产生式未指明的一个句法限制是空白符不允许在 stringprefix 或 bytesprefix 与字面值的其余部分之间出现。 源字符集是由编码格式声明来定义的。也就是说,两种类型的字面值都可用成对的单引号 (') 或双引号 (") 括起来。 它们还可以用成对的连续三个单引号或双引号括起来 (这通常被称为 三重引号字符串)。 反斜杠 (\) 字符被用来给予普通的字符特殊含义例如 n,当用斜杠转义时 (\n) 表示 '换行'。 它还可以被用来对具有特殊含义的字符进行转义,例如换行符、反斜杠本身或者引号等。

字节串字面值要加前缀 'b' 或 'B';生成的是类型 bytes 的实例,不是类型 str 的实例;字节串只能包含 ASCII 字符;字节串数值大于等于 128 时,必须用转义表示。字符串和字节串都可以加前缀 'r' 或 'R',称为 原始字符串,原始字符串把反斜杠当作原义字符,不执行转义操作。因此,原始字符串不转义 '\U' 和 '\u'。与 Python 2.x 的原始 unicode 字面值操作不同,Python 3.x 现已不支持 'ur' 句法。

3.3 新版功能:

  • 新增原始字节串 'rb' 前缀,是 'br' 的同义词;
  • 支持 unicode 字面值(u'value')遗留代码,简化 Python 2.x 和 3.x 并行代码库的维护工作。

前缀为 'f' 或 'F' 的字符串称为 格式字符串;详见 格式字符串字面值。'f' 可与 'r' 连用,但不能与 'b' 或 'u' 连用,因此,可以使用原始格式字符串,但不能使用格式字节串字面值。

三引号字面值可以包含未转义的换行和引号(原样保留),除了连在一起的,用于终止字面值的,未经转义的三个引号。("引号" 是启用字面值的字符,可以是 ',也可以是 "。)

转义序列

如未标注 'r' 或 'R' 前缀,字符串和字节串字面值中,转义序列以类似 C 标准的规则进行解释。可用的转义序列如下:

转义序列 含意 备注
\<newline> 忽略反斜杠与换行符 -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 位 16 进制数 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、必须为 4 个十六进制数码。

7、表示任意 Unicode 字符,必须为 8 个十六进制数码。

与 C 标准不同,Python 无法识别的转义序列在字符串中会原样保留,即输出结果会包含反斜杠。这种方式在调试时非常有用,因为当输错转义序列时,更容易在输出结果中识别错误。需要注意的是,在字节串字面值内,字符串字面值专用的转义序列被视为无法识别的转义序列。

即使在原始字面值中,引号也可以用反斜杠转义,但反斜杠会保留在输出结果里。例如,r"" 是由两个字符组成的有效字符串字面值:反斜杠和双引号;而 r"" 则不是有效字符串字面值(原始字符串也不能以单个反斜杠结尾)。特别是,原始字面值不能以单个反斜杠结尾(反斜杠会转义其后的引号)。还要注意,反斜杠加换行在字面值中被解释为两个字符,而不是连续行。

二、字符串字面值合并

以空白符分隔的多个相邻字符串或字节串字面值,可用不同引号标注,等同于合并操作。因此,"hello" 'world' 等价于 "helloworld"。此功能不需要反斜杠,即可将长字符串分为多个物理行,还可以为不同部分的字符串添加注释,例如:

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

注意:此功能在句法层面定义,在编译时实现。在运行时,合并字符串表达式必须使用 '+' 运算符。还要注意,字面值合并可以为每个部分应用不同的引号风格(甚至混用原始字符串和三引号字符串),格式字符串字面值也可以与纯字符串字面值合并。

三、格式字符串字面值

Python3.6 版开始,格式字符串字面值 或称 f-string 是标注了 '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>

双花括号 '{{' 或 '}}' 被替换为单花括号,花括号外的字符串仍按字面值处理,单左花括号 '{' 标记以 Python 表达式开头的替换字段,在表达式后加等于号 '=',可在求值后,同时显示表达式文本及其结果(用于调试)。 随后是用叹号 '!' 标记的转换字段。还可以在冒号 ':' 后附加格式说明符。替换字段以右花括号 '}' 为结尾。

格式化字符串字面值中的表达式会与用圆括号包围的常规 Python 表达式一样处理,但有少量例外。 空表达式是不被允许的,而 lambda 和赋值表达式 := 都必须显式地用括号包围。 每个表达式都将在格式化字符串字面值出现的上下文中按从左到右的顺序进行求值。 替换表达式可在单引号和三引号f-字符串中包含换行符并可包含注释。 替换字段内 # 后面的所有内容都是注释(即使结尾花括号和引号也是)。 在这种情况下,替换字段必须在另一行中结束。

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

Python 3.7 以前, 因为实现的问题,不允许在格式字符串字面值表达式中使用 await 表达式与包含 async for 子句的推导式; 在 Python 3.12 之前,不允许在 f-字符串的替换字段中使用注释。

表达式里含等号 '=' 时,输出内容包括表达式文本、'=' 、求值结果。输出内容可以保留表达式中左花括号 '{' 后,及 '=' 后的空格。没有指定格式时,'=' 默认调用表达式的 repr()。指定了格式时,默认调用表达式的 str(),除非声明了转换字段 '!r'。

指定了转换符时,表达式求值的结果会先转换,再格式化。转换符 '!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

四、数值字面值

数值字面值有三种类型:整数、浮点数、虚数。没有复数字面值(复数由实数加虚数构成)。数值字面值不含正负号;实际上,-1 等负数是由一元运算符 '-' 和字面值 1 合成的。

五、整数字面值

整数字面值词法定义如下:

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 等基数说明符后。除了 0 以外,十进制数字的开头不允许有零。以免与 Python 3.0 版之前使用的 C 样式八进制字面值混淆。

整数字面值示例如下:

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

在 3.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 版更改: 现已支持在字面值中,用下划线分组数字。

七、虚数字面值

虚数字面值词法定义如下:

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

虚数字面值生成实部为 0.0 的复数。复数由一对浮点数表示,它们的取值范围相同。创建实部不为零的复数,则需添加浮点数,例如 (3+4j)。虚数字面值示例如下:

3.14j 10.j 10j .001j 1e100j 3.14e-10j 3.14_15_93j
广告合作
QQ群号:707632017

温馨提示:

1、本网站发布的内容(图片、视频和文字)以原创、转载和分享网络内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。邮箱:2942802716#qq.com。(#改为@)

2、本站原创内容未经允许不得转裁,转载请注明出处“站长百科”和原文地址。

目录