哪些字符被 split() 视为空白?

Which characters are considered whitespace by split()?

我正在移植一些在字符串上调用 split() 的 Python 2 代码,因此我需要知道它的确切行为。 The documentation 表示当您未指定 sep 参数时,"runs of consecutive whitespace are regarded as a single separator".

不幸的是,它没有指定 哪个 个字符。有一些明显的竞争者(如 space、制表符和换行符),但 Unicode 包含许多其他候选者。

哪些字符被split()认为是白色space?

由于答案可能是特定于实现的,所以我的目标是 CPython。

(注意:我自己研究了这个问题的答案,因为我在任何地方都找不到它,所以我会把它张贴在这里,希望对其他人有好处。)

不幸的是,这取决于您的字符串是 str 还是 unicode(至少,在 CPython 中 - 我不知道这种行为是否实际上是由任何地方的规范强制要求的) .

如果是str,答案很简单:

  • 0x09 选项卡
  • 0x0a换行
  • 0x0b 垂直制表符
  • 0x0c 换页
  • 0x0d马车Return
  • 0x20 Space

来源:这些是 Python/pyctype.c, which are used by Py_ISSPACE, which is used by STRINGLIB_ISSPACE, which is used by split_whitespace.

中带有 PY_CTF_SPACE 的字符

如果是unicode,则有29个字符,除上述外还有:

  • U+001c0x001f:File/Group/Record/Unit 分隔符
  • U+0085: 下一行
  • U+00a0:不间断 Space
  • U+1680:奥格姆Space马克
  • U+20000x200a:各种固定大小的空间(例如 Em Space),但请注意零宽度 Space 不是 包括
  • U+2028: 行分隔符
  • U+2029:段落分隔符
  • U+202f:窄不间断 Space
  • U+205f:中等数学Space
  • U+3000:表意文字Space

请注意,前四个也是有效的 ASCII 字符,这意味着 纯 ASCII 字符串可能会根据它是 str 还是 unicode 进行不同的拆分!

来源:这些是 _PyUnicode_IsWhitespace, which is used by Py_UNICODE_ISSPACE, which is used by STRINGLIB_ISSPACE 中列出的字符(看起来它们对 strunicode 使用相同的函数实现,但对每种类型分别编译,某些宏的实现方式不同)。文档字符串对这组字符的描述如下:

Unicode characters having the bidirectional type 'WS', 'B' or 'S' or the category 'Zs'

Aasmund Eldhuset 的回答正是我试图做的,但我被打败了。它显示了大量的研究,绝对应该是公认的答案。

如果你想确认那个答案(或者只是想在不同的实现中测试它,比如非 CPython 的实现,或者可能使用不同 Unicode 标准的更新的实现covers), 下面的短程序将打印出使用 .split() 不带参数时导致拆分的实际字符。

它通过构造一个由 ab 字符 (a) 被测试字符分隔的字符串来实现,然后检测是否 split 创建一个多于一个元素的数组:

int_ch = 0
while True:
    try:
        test_str = "a" + chr(int_ch) + "b"
    except Exception as e:
        print(f'Stopping, {e}')
        break
    if len(test_str.split()) != 1:
        print(f'0x{int_ch:06x} ({int_ch})')
    int_ch += 1

输出(对于我的系统)如下:

0x000009 (9)
0x00000a (10)
0x00000b (11)
0x00000c (12)
0x00000d (13)
0x00001c (28)
0x00001d (29)
0x00001e (30)
0x00001f (31)
0x000020 (32)
0x000085 (133)
0x0000a0 (160)
0x001680 (5760)
0x002000 (8192)
0x002001 (8193)
0x002002 (8194)
0x002003 (8195)
0x002004 (8196)
0x002005 (8197)
0x002006 (8198)
0x002007 (8199)
0x002008 (8200)
0x002009 (8201)
0x00200a (8202)
0x002028 (8232)
0x002029 (8233)
0x00202f (8239)
0x00205f (8287)
0x003000 (12288)
Stopping, chr() arg not in range(0x110000)

你可以忽略最后的错误,这只是为了确认它不会失败,直到我们移出有效的 Unicode 区域(代码点 0x000000 - 0x10ffff 构成十七个平面)。


(a) 希望 Python 的未来版本不会考虑 ab 为空格,因为这会完全破坏此(以及许多其他)代码。

我认为这种可能性很小,所以应该没问题:-)