isdecimal和isdigit的区别
Python 3中关于 isdigit
的说明是这样的:
如果字符串中的所有字符都是数字,并且至少有一个字符,就返回真;否则返回假。数字包括十进制字符,还有一些需要特殊处理的数字,比如上标数字。简单来说,数字是指那些被标记为 Numeric_Type=Digit 或 Numeric_Type=Decimal 的字符。
所以看起来 isdigit
应该包含 isdecimal
的所有内容。但接下来 isdecimal
的说明是:
如果字符串中的所有字符都是十进制字符,并且至少有一个字符,就返回真;否则返回假。十进制字符是属于“Nd”这一类的字符。这一类包括数字字符,以及所有可以用来组成十进制数字的字符,比如 U+0660,阿拉伯-印度数字零。
这听起来像是 isdecimal
应该包含 isdigit
的所有内容。
那么这两个方法之间有什么关系呢?其中一个是否匹配了另一个的严格超集?Numeric_Type 属性和 Nd 类别之间有关系吗?(而且这种矛盾的说明算不算是文档错误呢?)
3 个回答
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的文档则是错误的。
我理解的《Unicode 6.0标准》第4.6节是,数字类别是十进制数字类别的一个超集。
十进制数字,简单来说,就是用来表示十进制数的数字。它们包括特定语言的数字,但不包括像罗马数字和希腊的数字那样的字符,因为这些字符不能用来表示十进制数。(注意,<1, 5> = 15 = 十五,但 IV = 四。)
Numeric_Type=decimal这个属性值(与General_Category=Nd属性值相关)只包括那些用于十进制数的数字字符,并且这些字符在编码时是连续的,数字值是递增的,数字零是这个范围内的第一个编码点。
所以,十进制类别不包括像罗马数字、分数等其他类型的数字。
正如我在发现的,检查字符串是否为数字的条件和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