为什么第一个表达式被解释为整数,而第二个表达式被解释为字符串?

4
使用 PyYaml
import yaml

yaml.full_load(StringIO('a: 16:00:00'))
# {'a': 57600}
yaml.full_load(StringIO('a: 09:31:00'))
# {'a': '09:31:00'}

为什么这些行为会有差异?

1
可能是因为前导零触发解析为八进制数,但09不是有效的八进制数,所以YAML退回到字符串。YAML有很多问题。许多问题。(等等,实际上不是这样的;八进制解析也是一个问题,但对于看起来像时间戳的东西,YAML显然从不接受前导零。) - Konrad Rudolph
2
虽然不算是重复,但可以参考此答案中提供的信息。较早版本的YAML规范允许使用六十进制数(基本上,使用“:”分隔“数字”,而不是使用60个不同字符)的形式。PyYAML仍然尝试解析它们,即使它们已被从YAML 1.2中删除。 - chepner
2个回答

4

旧版本的YAML支持60进制数字,旨在用于时间等。它不是像十六进制使用0-9和A-F这样的附加数字,而是使用由冒号:分隔的十进制数0-59。因此,16:00:00等同于

16*(60**2) + 0*60 + 0 == 57600.

PyYAML 显然仍在使用旧的 YAML 规范。

09:30:00,然而,不以有效的十进制数开始:前导零表示一个八进制数,但09不是有效的八进制数。无法将其解析为任何已知数字类型(八进制、十进制或六十进制),PyYAML 回退到字符串。

YAML 可以表示时间戳,但只有当它们由日期和可选时间戳组成时才能表示。PyYAML 将这些时间戳解析为 datetime.datetime 对象,这似乎是合理的。

>>> yaml.full_load(StringIO('a:   2022-12-21T09:31:00'))
{a: datetime.datetime(2022, 12, 21, 9, 31)}

我在评论中引用了一个答案,https://dev59.com/WIjca4cB1Zd3GeqPv2To#45165433,这个答案由另一个软件包的作者提供,它符合YAML 1.2规范,将会把值解析为字符串而不是六十进制整数。

>>> from ruamel import yaml
>>> yaml.safe_load('a: 16:00:00')
{'a': '16:00:00'}

1
尽管 PyYAML 自 2020 年以来没有更新,但我真的不明白为什么它从未添加对于在 2009 年发布的 YAML 1.2 的支持。现在 ruamel.yaml 明显是更好的选择。 - CrazyChucky

1
取决于时间戳 09:31:00 的标题 0:去掉它,你就能得到整数值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接