2016-07-01 3 views
1

Согласно the Python 2.7 docs, с использованием str.split() с указанным maxsplit будет разделена строка до maxsplit раз.Есть ли какие-либо гарантии относительно порядка расщепления str.split()?

Однако он никогда явно не указывает, что эти расщепления будут выполняться слева направо. Существует связанная с этим функция str.rsplit(), которая гарантирует право на разделение налево.

Помимо того, что вы выполняете строчку в обратном порядке, а затем str.rsplit(), есть ли способ гарантировать право на право расщепления? Существуют ли какие-либо ситуации, когда str.split() НЕ будет использовать порядок слева направо?

+5

'str.split' всегда разделяет слева направо,' .rsplit' другой путь. – jonrsharpe

+0

Это никогда не указывается в документах. Где вы получаете гарантию? Я понимаю, что эмпирически это результат, но наблюдения не являются гарантией. – Connor

+2

@ConnorBlanck - Если вы хотите, вы можете посмотреть на реализацию. Расщепление ltr - это намерение метода - 'maxsplit' было бы практически бесполезно, если бы вы не могли сказать _where_, что произойдет расщепление. Я догадываюсь, что авторы документов просто посчитали это слишком очевидным. Если вы чувствуете, что это необходимо в документации, не стесняйтесь сообщать об ошибках в отношении документов. – mgilson

ответ

3

Если вы ищете гарантии, что разделение с аргументом maxsplit разделяется слева направо, вам нужно только посмотреть встроенный python test suite.

Вот отрывок:

self.checkequal(['a', 'b', 'c', 'd'], 'a|b|c|d', 'split', '|') 
    self.checkequal(['a|b|c|d'], 'a|b|c|d', 'split', '|', 0) 
    self.checkequal(['a', 'b|c|d'], 'a|b|c|d', 'split', '|', 1) 
    self.checkequal(['a', 'b', 'c|d'], 'a|b|c|d', 'split', '|', 2) 
    self.checkequal(['a', 'b', 'c', 'd'], 'a|b|c|d', 'split', '|', 3) 
    self.checkequal(['a', 'b', 'c', 'd'], 'a|b|c|d', 'split', '|', 4) 
    self.checkequal(['a', 'b', 'c', 'd'], 'a|b|c|d', 'split', '|', 
        sys.maxsize-2) 
    self.checkequal(['a|b|c|d'], 'a|b|c|d', 'split', '|', 0) 
    self.checkequal(['a', '', 'b||c||d'], 'a||b||c||d', 'split', '|', 2) 
    self.checkequal(['abcd'], 'abcd', 'split', '|') 
    self.checkequal([''], '', 'split', '|') 
    self.checkequal(['endcase ', ''], 'endcase |', 'split', '|') 
    self.checkequal(['', ' startcase'], '| startcase', 'split', '|') 
    self.checkequal(['', 'bothcase', ''], '|bothcase|', 'split', '|') 
    self.checkequal(['a', '', 'b\x00c\x00d'], 'a\x00\x00b\x00c\x00d', 'split', '\x00', 2) 

Из испытаний, то ясно, что любая реализация, что сделали что-то другое потерпит неудачу этих тестов.

+0

Это довольно хорошая гарантия. Я увижу, как документы должны указывать это предположение. Благодарю. – Connor

2

CPython считается эталонной реализацией Python. Согласно исходному коду CPython, str.split будет расколоться в порядке слева направо. Вы можете посмотреть, как str.split реализуется, вот ссылка http://svn.python.org/view/python/tags/r271/Objects/stringlib/split.h?view=markup

Например, в stringlib_split_char (а также в stringlib_split_whitespace, которые оба используются в stringlib_split (str.split)) ясно видно, что строка обрабатывается с слева направо (i и j используются для индекса строки, они оба начинают с нуля, и в настоящее время увеличивается, maxsplit не влияет на показатели рассматриваются, maxsplit только обеспечивает ранний выход из цикла):

Py_LOCAL_INLINE(PyObject *) 
stringlib_split_char(PyObject* str_obj, 
        const STRINGLIB_CHAR* str, Py_ssize_t str_len, 
        const STRINGLIB_CHAR ch, 
        Py_ssize_t maxcount) 
{ 
    // ... some code omitted 

    i = j = 0; 
    while ((j < str_len) && (maxcount-- > 0)) { 
     for(; j < str_len; j++) { 
      /* I found that using memchr makes no difference */ 
      if (str[j] == ch) { 
       SPLIT_ADD(str, i, j); 
       i = j = j + 1; 
       break; 
      } 
     } 
    } 
    // ... some code omitted 

И в stringlib_rsplit_char (используется в str.rsplit) оба i и j индексы начинаются в конце строки и быть декрементируется:

i = j = str_len - 1; 
while ((i >= 0) && (maxcount-- > 0)) { 
    for(; i >= 0; i--) { 
     if (str[i] == ch) { 
      SPLIT_ADD(str, i + 1, j + 1); 
      j = i = i - 1; 
      break; 
     } 
    } 
+1

Обратите внимание, что * «как [это] реализовано» * ** не ** так же, как и гарантировано ли для какой-либо конкретной реализации. – jonrsharpe

+0

cpython считается ссылочной реализацией языка python – NickAb

+0

* Учитывается *, да. Вы можете добавить это в ответ и отметить, что это должна быть * ссылка * not * a *! – jonrsharpe

Смежные вопросы