处理字符串时的 str.isdigit() 行为

Lac*_*bus 16 python python-3.x

假设如下:

\n
>>> square = '\xc2\xb2'      # Superscript Two (Unicode U+00B2)\n>>> cube  = '\xc2\xb3'       # Superscript Three (Unicode U+00B3)\n
Run Code Online (Sandbox Code Playgroud)\n

奇怪的是:

\n
>>> square.isdigit()\nTrue\n>>> cube.isdigit()\nTrue\n
Run Code Online (Sandbox Code Playgroud)\n

好的,让我们将这些“数字”转换为整数:

\n
>>> int(square)\nTraceback (most recent call last):\n  File "<stdin>", line 1, in <module>\nValueError: invalid literal for int() with base 10: '\xc2\xb2'\n>>> int(cube)\nTraceback (most recent call last):\n  File "<stdin>", line 1, in <module>\nValueError: invalid literal for int() with base 10: '\xc2\xb3'\n
Run Code Online (Sandbox Code Playgroud)\n

哎呀!

\n

有人可以解释一下我应该期待什么行为吗str.isdigit()在处理字符串时我应该从该方法中得到什么行为吗?

\n

Sha*_*ger 20

str.isdigit并不声称与可解析性相关int。它报告一个简单的 Unicode 属性,是十进制字符还是某种数字:

str.isdigit()

True如果字符串中所有字符都是数字并且至少有一个字符,则返回,否则返回False。数字包括十进制字符和需要特殊处理的数字,例如兼容性上标数字。这涵盖了不能用来构成以 10 为基数的数字的数字,例如 Kharosthi 数字。形式上,数字是具有属性值 Numeric_Type=Digit 或 Numeric_Type=Decimal 的字符。

简而言之,str.isdigit对于检测有效数字完全没有用。检查给定字符串是否是合法整数的正确解决方案是调用int它,并捕获ValueError它是否不是合法整数。您所做的任何其他事情都将(糟糕地)重新发明实际解析代码执行的相同测试int(),那么为什么不首先让它完成这项工作呢?

旁注:您错误地使用了术语“utf-8”。UTF-8 是一种特定的 Unicode 编码方式,仅适用于原始二进制数据。Pythonstr是一种“理想化”的 Unicode 文本类型;它没有编码(在底层,它存储编码为 ASCII、latin-1、UCS-2、UCS-4 和可能还有 UTF-8 之一,但除了间接测量之外,这些在 Python 层中都不可见就像sys.getsizeof,它只是通过让您查看字符串消耗了多少内存来暗示底层编码)。您所讨论的字符是 ASCII 范围以上的简单 Unicode 字符,它们并不是专门的 UTF-8。

  • @flakes:“isnumeric”更糟糕;它对“isdigit”涵盖的所有内容返回“True”,以及第三个类别“Numeric_Type=Numeric”。`isdecimal` 似乎是最严格的测试(事实上,`'²'.isdecimal()` 返回 `False`,与 `isdigit` 和 `isnumeric` 不同),因此它让您更接近于构成有效 ` int`,但同样,“这是合法的‘int’吗?”的正确解决方案 是“调用 `int()` 并在失败时捕获 `ValueError`”;对字符串属性的预检查总是要么太严格(“-2”不会通过这些测试,但“int()”可以解析它)要么太宽松(允许“²”等)。 (4认同)
  • 我不知道“isdigit”会这样做。这对于“isnumeric”是否成立?我将不得不 grep 我的 github 组织来解决这个问题并明天修复它。 (2认同)
  • @flakes:“isnumeric”对于检测字符串是否代表数字也没有用。它测试 Unicode 属性 Numeric_Type=Digit、Numeric_Type=Decimal 或 Numeric_Type=Numeric 的字符。 (2认同)
  • 请注意,Numeric_Type=Digit 不再用于新字符,因此“isdigit”执行的测试现在比以前更没有用处 - 以前接收 Numeric_Type=Digit 的新字符现在接收 Numeric_Type=Numeric。请参阅 [Unicode 标准 14.0 第 4.6 章](https://www.unicode.org/versions/Unicode14.0.0/ch04.pdf)。 (2认同)