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;参见 编码声明

自然语言描述: 两种字面值都可以用成对单引号 (') 或双引号 (") 来标示首尾。它们也可以用成对的连续三个单引号或双引号来标示首尾 (这通常被称为 三引号字符串)。反斜杠 (\) 字符被用来对特殊含义的字符进行转义,例如换行,反斜杠本身或是引号等字符。

字节串字面值总是带有前缀 'b''B';它们生成 bytes 类型而非 str 类型的实例。它们只能包含 ASCII 字符;字节对应数值在128及以上必须以转义形式来表示。

字符串和字节串字面值都可以带有前缀 'r''R';这种字符串被称为 原始字符串 其中的反斜杠会被当作其本身的字面字符来处理。因此在原始字符串字面值中,'\U''\u' 转义形式不会被特殊对待。由于 Python 2.x 的原始统一码字面值的特性与 Python 3.x 不一致,'ur' 语法已不再被支持。

3.3 新版功能: 新加入了表示原始字节串的 'rb' 前缀,与 'br' 的意义相同。

3.3 新版功能: 对旧式统一码字面值 (u'value') 的支持被重新引入以简化 Python 2.x 和 3.x 代码库的同步维护。详情见 PEP 414

包含 'f''F' 前缀的字符串字面值称为 格式化字符串字面值;参见 格式化字符串字面值'f' 可与 'r' 连用,但不能与 'b''u' 连用,因此存在原始格式化字符串,但不存在格式化字节串字面值。

在三引号字面值中,允许存在未经转义的换行和引号 (并原样保留),除非是未经转义的连续三引号,这标示着字面值的结束。 ("引号" 是用来标示字面值的字符,即 '"。)

除非带有 'r''R' 前缀,字符串和字节串字面值中的转义序列会基于类似标准 C 中的转义规则来解读。可用的转义序列如下:

转义序列 意义 注释
\newline 反斜杠加换行全被忽略  
\\ 反斜杠 (\)  
\' 单引号 (')  
\" 双引号 (")  
\a ASCII 响铃 (BEL)  
\b ASCII 退格 (BS)  
\f ASCII 进纸 (FF)  
\n ASCII 换行 (LF)  
\r ASCII 回车 (CR)  
\t ASCII 水平制表 (TAB)  
\v ASCII 垂直制表 (VT)  
\ooo 八进制数 ooo 码位的字符 (1,3)
\xhh 十六进制数 hh 码位的字符 (2,3)

仅在字符串字面值中可用的转义序列如下:

转义序列 意义 注释
\N{name} Unicode 数据库中名称为 name 的字符 (4)
\uxxxx 16位十六进制数 xxxx 码位的字符 (5)
\Uxxxxxxxx 32位16进制数 xxxxxxxx 码位的字符 (6)

注释:

  1. 与标准 C 一致,接受最多三个八进制数码。

  2. 与标准 C 不同,要求必须为两个十六进制数码。

  3. 在字节串字面值中,十六进制数和八进制数转义码以相应数值代表每个字节。在字符串字面值中,这些转义码以相应数值代表每个 Unicode 字符。

  4. 在 3.3 版更改: 加入了对别名 [1] 的支持。

  5. 要求必须为四个十六进制数码。

  6. 此方式可用来表示任意 Unicode 字符。要求必须为八个十六进制数码。

与标准 C 不同,所有无法识别的转义序列将原样保留在字符串中,也就是说,反斜杠会在结果中保留。(这种方式在调试时很有用: 如果输错了一个转义序列,更容易在输出结果中识别错误。) 另外要注意的一个关键点是:专用于字符串字面值中的转义序列如果在字节串字面值中出现,会被归类为无法识别的转义序列。

在 3.6 版更改: 无法识别的转义序列会引发 DeprecationWarning。从未来某个 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. 格式化字符串字面值

3.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 表达式必须显式地加上圆括号。替换表达式可以包含换行 (例如在三引号字符串中),但是不能包含注释。每个表达式会在格式化字符串字面值所包含的位置按照从左至右的顺序被求值。

如果指定了转换符,表达式的求值结果会先转换再格式化。转换符 '!s' 即对结果调用 str()'!r' 为调用 repr(),而 '!a' 为调用 ascii()

在此之后结果会使用 format() 协议进行格式化。格式说明符会被传入表达式或转换结果的 __format__() 方法。如果省略格式说明符则会传入一个空字符串。然后格式化结果会包含在整个字符串最终的值当中。

顶层的格式说明符可以包含有嵌套的替换字段。这些嵌套字段也可以包含有自己的转换字段和 格式说明符,但不可再包含更深层嵌套的替换字段。这里的 格式说明符微型语言 与字符串 .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'
>>> number = 1024
>>> f"{number:#0x}"  # using integer format specifier
'0x400'

与正常字符串字面值采用相同语法导致的一个结果就是替换字段中的字符不能与外部的格式化字符串字面值所用的引号相冲突:

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

格式表达式中不允许有反斜杠,这会引发错误:

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

想包含需要用反斜杠转义的值,可以创建一个临时变量。

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

格式化字符串字面值不可用作文档字符串,即便其中没有包含表达式。

>>>
>>> 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 之后。

注意非零的十进制数开头不允许有额外的零。这是为了避免与 Python 在版本 3.0 之前所使用的 C 风格八进制字面值相混淆。

一些整型数字面值的示例如下:

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 词法中使用。如果出现于字符串字面值和注释之外将无条件地引发错误:

$       ?       `

脚注

::...
免责声明:
当前网页内容, 由 大妈 ZoomQuiet 使用工具: ScrapBook :: Firefox Extension 人工从互联网中收集并分享;
内容版权归原作者所有;
本人对内容的有效性/合法性不承担任何强制性责任.
若有不妥, 欢迎评注提醒:

或是邮件反馈可也:
askdama[AT]googlegroups.com



自怼圈/年番新

DU21.4
关于 ~ DebugUself with DAMA ;-)


关注公众号, 持续获得相关各种嗯哼:
zoomquiet


粤ICP备18025058号-1
公安备案号: 44049002000656 ...::