Ответ 1
str.split
дополняет str.join
, поэтому
"/".join(['', 'segment', 'segment', ''])
возвращает исходную строку.
Если пустых строк не было, первый и последний '/'
будут отсутствовать после join()
В чем смысл '/segment/segment/'.split('/')
возврата ['', 'segment', 'segment', '']
?
Обратите внимание на пустые элементы. Если вы делитесь на разделитель, который находится в позиции один и в самом конце строки, какое дополнительное значение дает вам, чтобы пустая строка возвращалась с каждого конца?
str.split
дополняет str.join
, поэтому
"/".join(['', 'segment', 'segment', ''])
возвращает исходную строку.
Если пустых строк не было, первый и последний '/'
будут отсутствовать после join()
Здесь есть два основных момента:
'/segment/segment/'.split('/')
будет равен ['segment', 'segment']
, но тогда это потеряет информацию. Если split()
работал так, как вам хотелось, если я скажу вам, что a.split('/') == ['segment', 'segment']
, вы не можете сказать мне, что было a
.'a//b'.split()
be? ['a', 'b']
?, или ['a', '', 'b']
? I.e., следует split()
объединить смежные разделители? Если это так, то будет очень сложно разобрать данные, которые ограничены символом, а некоторые из полей могут быть пустыми. Я уверен, что есть много людей, которые хотят получить пустые значения в результате для вышеуказанного случая!В конце концов, это сводится к двум вещам:
Согласованность: если у меня есть n
разделители, в a
, я получаю значения n+1
после split()
.
Должно быть возможно делать сложные вещи и легко выполнять простые вещи: если вы хотите игнорировать пустые строки в результате split()
, вы всегда можете сделать:
def mysplit(s, delim=None):
return [x for x in s.split(delim) if x]
но если вы не хотите игнорировать пустые значения, вы должны иметь возможность.
Язык должен выбрать одно определение split()
— существует слишком много различных вариантов использования, чтобы удовлетворить все требования по умолчанию. Я думаю, что выбор Python является хорошим и является наиболее логичным. (В стороне одна из причин, по которым мне не нравится C strtok()
, заключается в том, что она объединяет смежные разделители, что делает ее чрезвычайно трудной для серьезного анализа/токенизации с ней.)
Есть одно исключение: a.split()
без аргумента сжимает последовательное белое пространство, но можно утверждать, что в этом случае это правильно. Если вы не хотите поведения, вы всегда можете a.split(' ')
.
В общем случае, чтобы удалить пустые строки, возвращенные в результатах split()
, вы можете посмотреть функцию filter
.
Пример:
filter(None, '/segment/segment/'.split('/'))
возвращает
['segment', 'segment']
Имея x.split(y)
всегда возвращать список элементов 1 + x.count(y)
, является ценной регулярностью - как уже указывал @gnibbler, он делает точные инверсии split
и join
друг друга (как они должны быть) он также точно отображает семантику всех типов записей, связанных с разделителями (например, csv
строки файла [[net of quotings issues]], строки из /etc/group
в Unix и т.д.), он позволяет (как @Roman ответ упомянут) легко проверяет (например) абсолютные vs относительные пути (в пути к файлам и URL-адреса) и т.д.
Другим способом взглянуть на это является то, что вы не должны просто бросать информацию из окна без усиления. Что получится при создании x.split(y)
эквивалентного x.strip(y).split(y)
? Ничего, конечно, легко использовать вторую форму, если это то, что вы имеете в виду, но если первая форма была условно признана второй, вам нужно будет много работы, когда вы сделаете нужен первый (что далеко не редко, как указывает предыдущий пункт).
Но на самом деле мышление с точки зрения математической закономерности - это самый простой и общий способ научить себя разрабатывать проходимые API. Чтобы принять другой пример, очень важно, чтобы для любых действительных x
и y
x == x[:y] + x[y:]
, что сразу же указывает, почему исключить одну крайность разреза. Более простое утверждение, которое вы можете сформулировать, более вероятно, что полученная семантика - это то, что вам нужно в реальных жизненных целях - часть мистического факта, что математика очень полезна при работе со Вселенной.
Попробуйте сформулировать инвариант для диалекта split
, в котором лидирующие и конечные разделители являются специальными общими... counter-example: строковые методы, такие как isspace
, не являются максимально простыми - x.isspace()
эквивалентно x and all(c in string.whitespace for c in x)
- то, что глупое лидерство x and
заключается в том, почему вы так часто находите себе кодирование not x or x.isspace()
, чтобы вернуться к простоте, которая должна была быть разработана в строковых методах is...
(при этом пустая строка "есть" что угодно хотеть - вопреки здравому смыслу человека в дороге, возможно [[пустые множества, как ноль и с, всегда путают большинство людей;-)]], но полностью соответствуют очевидным, смысл -.)
Я не уверен, какой ответ вы ищете? Вы получаете три матча, потому что у вас три разделителя. Если вы не хотите этого пустого, просто используйте:
'/segment/segment/'.strip('/').split('/')
Хорошо, это позволяет вам знать, что там был разделитель. Итак, видя 4 результата, вы знаете, что у вас есть 3 разделителя. Это дает вам возможность делать все, что вам нужно, с этой информацией, вместо того, чтобы Python удалял пустые элементы, а затем вручную проверял запуск или завершение разделителей, если вам нужно это знать.
Простой пример: скажем, вы хотите проверить абсолютные и относительные имена файлов. Таким образом, вы можете сделать все это с помощью раскола, не требуя также проверки того, что является первым символом вашего имени файла.