isdecimal和isdigit的区别

9 投票
3 回答
2466 浏览
提问于 2025-04-17 21:36

Python 3中关于 isdigit 的说明是这样的:

如果字符串中的所有字符都是数字,并且至少有一个字符,就返回真;否则返回假。数字包括十进制字符,还有一些需要特殊处理的数字,比如上标数字。简单来说,数字是指那些被标记为 Numeric_Type=Digit 或 Numeric_Type=Decimal 的字符。

所以看起来 isdigit 应该包含 isdecimal 的所有内容。但接下来 isdecimal 的说明是:

如果字符串中的所有字符都是十进制字符,并且至少有一个字符,就返回真;否则返回假。十进制字符是属于“Nd”这一类的字符。这一类包括数字字符,以及所有可以用来组成十进制数字的字符,比如 U+0660,阿拉伯-印度数字零。

这听起来像是 isdecimal 应该包含 isdigit 的所有内容。

那么这两个方法之间有什么关系呢?其中一个是否匹配了另一个的严格超集?Numeric_Type 属性和 Nd 类别之间有关系吗?(而且这种矛盾的说明算不算是文档错误呢?)

3 个回答

2

Python 3

Python 3的文档对str.isdecimal的说明似乎已经修正,现在不再说小数包括数字了:

str.isdecimal

如果字符串中的所有字符都是小数字符,并且至少有一个字符,就返回真;否则返回假。小数字符是指可以用来组成十进制数字的字符,比如U+0660,阿拉伯-印度数字零。正式来说,小数字符属于Unicode的一种分类“Nd”。

Python 2

Python 2的文档似乎仍然是错误的(与2.7.14的实现不符),并且始终表示小数包括数字:

str.isdigit

如果字符串中的所有字符都是数字,并且至少有一个字符,就返回真;否则返回假。对于8位字符串,这个方法依赖于地区设置。

unicode.isdecimal

如果S中只有小数字符,就返回真;否则返回假。小数字符包括数字字符,以及所有可以用来组成十进制数字的字符,比如U+0660,阿拉伯-印度数字零。

在Python 2.7.14中快速测试字符'³'显示小数确实包括数字:

>>> u'\u00b3'.isdecimal()
False
>>> u'\u00b3'.isdigit()
True

总结

Python 2和3现在的行为相似(数字包括小数),与Python 3的文档一致,而Python 2的文档则是错误的。

3

我理解的《Unicode 6.0标准》第4.6节是,数字类别是十进制数字类别的一个超集。

十进制数字,简单来说,就是用来表示十进制数的数字。它们包括特定语言的数字,但不包括像罗马数字和希腊的数字那样的字符,因为这些字符不能用来表示十进制数。(注意,<1, 5> = 15 = 十五,但 IV = 四。)

Numeric_Type=decimal这个属性值(与General_Category=Nd属性值相关)只包括那些用于十进制数的数字字符,并且这些字符在编码时是连续的,数字值是递增的,数字零是这个范围内的第一个编码点。

所以,十进制类别不包括像罗马数字、分数等其他类型的数字。

5

正如我在发现的,检查字符串是否为数字的条件和Unicode字符属性之间的对应关系如下:

isdecimal: Nd,
isdigit:   No, Nd,
isnumeric: No, Nd, Nl,
isalnum:   No, Nd, Nl, Lu, Lt, Lo, Lm, Ll,

例如,ᛰ(古代北欧符号,U+16F0)属于Nl,因此:

'ᛰ'.isdecimal() # False
'ᛰ'.isdigit()   # False
'ᛰ'.isnumeric() # True
'ᛰ'.isalnum()   # True

撰写回答