Подтвердить что ты не робот

Почему Python `re.split()` разделяется на нулевую длину?

Одна особенность (в противном случае довольно мощного) модуля re в Python заключается в том, что re.split() никогда не разделит строку на нулевую длину, например, если я хочу разбить строку по границам слов:

>>> re.split(r"\s+|\b", "Split along words, preserve punctuation!")
['Split', 'along', 'words,', 'preserve', 'punctuation!']

вместо

['', 'Split', 'along', 'words', ',', 'preserve', 'punctuation', '!']

Почему это ограничение? Это по дизайну? Существуют ли другие приемы регулярных выражений?

4b9b3361

Ответ 1

Это дизайнерское решение, которое было сделано и могло пойти в любом случае. Тим Петерс сделал этот пост, чтобы объяснить:

Например, если вы разделите "abc" по шаблону x *, что вы делаете ожидать? Шаблон соответствует (с длиной 0) в 4 местах, но я уверен, что большинство людей были бы удивлены, увидев

['', 'a', 'b', 'c', '']

назад вместо (как они это делают)

['abc']

Тем не менее некоторые другие не согласны с ним. Guido van Rossum не хочет, чтобы он менялся из-за проблем с обратной совместимостью. Он сделал сказать:

Я согласен с добавлением флага, чтобы включить это поведение.

Edit

Существует обходной путь, размещенный Ян Бурджи:

>>> s = "Split along words, preserve punctuation!"
>>> re.sub(r"\s+|\b", '\f', s).split('\f')
['', 'Split', 'along', 'words', ',', 'preserve', 'punctuation', '!']

Где '\f' можно заменить любым неиспользуемым символом.

Ответ 2

Чтобы обойти эту проблему, вы можете использовать режим VERSION1 regex package, который делает split() производить нулевую длину также:

>>> import regex as re
>>> re.split(r"\s+|\b", "Split along words, preserve punctuation!", flags=re.V1)
['', 'Split', 'along', 'words', ',', 'preserve', 'punctuation', '!']

Ответ 3

В принципе, split() - это две разные функции в одну. Если вы предоставляете параметр, он ведет себя совсем по-другому, чем при вызове без него.

Сначала кажется, что

s.split() == s.split(' \t\n')

но это не так, как вы показали. Док говорит:

[...] Если sep не указан или None, любая строка пробелов является разделителем, и пустые строки удаляются из результата. [...]

Даже добавив параметр "remove_empty", он все равно будет вести себя странно, потому что значение по умолчанию "remove_empty" зависит от параметра "sep".