5

Python的str.format()方法的简单使用:

>>> '{0}'.format('zero')
'zero'

十六进制、八进制和二进制文字不起作用:

>>> '{0x0}'.format('zero')
KeyError: '0x0'
>>> '{0o0}'.format('zero')
KeyError: '0o0'
>>> '{0b0}'.format('zero')
KeyError: '0b0'

但是,根据替换字段语法,他们应该:

replacement_field ::=  "{" [field_name] ["!" conversion] [":" format_spec] "}"
field_name        ::=  arg_name ("." attribute_name | "[" element_index "]")*
arg_name          ::=  [identifier | integer]
attribute_name    ::=  identifier
element_index     ::=  integer | index_string
index_string      ::=  <any source character except "]"> +
conversion        ::=  "r" | "s"
format_spec       ::=  <described in the next section>

整数语法如下:

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

我是否误解了文档,或者 Python 的行为不像宣传的那样?(我使用的是 Python 2.7。)

4

1 回答 1

4

这看起来像是语法错误。文本没有什么可以澄清的;它只是将其描述为“数字或标识符”,并讨论如何解释它是否为数字。

测试一下,该字段显然不被视为integer

>>> '{08}'.format(*range(10)) # should be SyntaxError
'8'
>>> '{010}'.format(*range(10)) # should be '8'
'10'
>>> '{-1}'.format(*range(10)) # should be '9', but looked up as a string
KeyError: '-1'
>>> '{1 }'.format(*range(10)) # should be '1', but looked up as a string
KeyError: '1 '
>>> '{10000000000000000000}'.format(1) # should be IndexError
ValueError: Too many decimal digits in format string

看代码,它并没有借用 Python 解析器来解析格式字符串;它使用自定义解析,将 arg_spec 解释为数字的代码使用一个get_integer函数,该函数仅转换每个数字并移位和添加,直到字段结束或我们进入PY_SSIZE_T_MAX.

PEP 3101表明这是故意的:

简单的字段名称是名称或数字。如果是数字,它们必须是有效的以 10 为底的整数……</p>

并没有具体说不能太接近最大索引值,也没有说不能使用负索引。但大多数其他怪癖可以通过使用“有效的 base-10 整数”描述而不仅仅是“整数”来解释。事实上,仅仅将其描述为digit +而不是integer解决所有的怪癖。

element_index解析方式与arg_name. #8985故意说element_index“……为整数索引使用最窄的定义,以便将所有其他字符串传递给映射。” 这是否也是故意的arg_name,或者是否是使用相同代码的意外结果,我不确定。

文档在3.4中没有变化,并且代码在当前主干中实际上没有变化。

我建议搜索错误跟踪器python-dev档案,看看之前是否有人提出过这个问题。如果没有,请弄清楚您是否认为应该更改文档或代码,提交错误并最好提交补丁。

于 2013-10-05T22:45:13.333 回答