파이썬에서 빈 문자열을 분할 할 때 split ()이 빈 목록을 반환하는 반면 split ( '\ n')은 [ '']를 반환하는 이유는 무엇입니까?


155

split('\n')하나의 문자열로 줄을 가져 오는 데 사용 하고 ''.split()있으며 빈 목록 을 반환하는 []반면을 ''.split('\n')반환합니다 ['']. 그러한 차이에 대한 특별한 이유가 있습니까?

그리고 문자열에서 줄을 계산하는 더 편리한 방법이 있습니까?


답변:


247

질문 : split ( '\ n')을 사용하여 한 문자열로 줄을 가져오고 ''.split ()이 빈 목록 []을 반환하는 반면 ''.split ( '\ n')은 [ '']을 반환한다는 것을 알았습니다. .

str.split () 메소드는 두 알고리즘을 갖는다. 인수가 제공되지 않으면 반복 된 공백 실행으로 분할됩니다. 그러나 인수가 제공되면 반복 실행이없는 단일 분리 문자로 처리됩니다.

빈 문자열을 분할하는 경우 첫 번째 모드 (인수 없음)는 공백이 먹고 결과 목록에 입력 할 값이 없기 때문에 빈 목록을 반환합니다.

반대로 두 번째 모드 (와 같은 인수 사용 \n)는 첫 번째 빈 필드를 생성합니다. 작성 '\n'.split('\n')했다면 두 개의 필드를 얻을 것입니다 (하나의 분할, 두 개의 반쪽 제공).

질문 : 그러한 차이에 대한 특별한 이유가 있습니까?

이 첫 번째 모드는 가변 양의 공백이있는 열에서 데이터를 정렬 할 때 유용합니다. 예를 들면 다음과 같습니다.

>>> data = '''\
Shasta      California     14,200
McKinley    Alaska         20,300
Fuji        Japan          12,400
'''
>>> for line in data.splitlines():
        print line.split()

['Shasta', 'California', '14,200']
['McKinley', 'Alaska', '20,300']
['Fuji', 'Japan', '12,400']

두 번째 모드는 반복되는 쉼표가 빈 필드를 나타내는 CSV와 같은 구분 된 데이터에 유용합니다. 예를 들면 다음과 같습니다.

>>> data = '''\
Guido,BDFL,,Amsterdam
Barry,FLUFL,,USA
Tim,,,USA
'''
>>> for line in data.splitlines():
        print line.split(',')

['Guido', 'BDFL', '', 'Amsterdam']
['Barry', 'FLUFL', '', 'USA']
['Tim', '', '', 'USA']

결과 필드 수는 분리 문자 수보다 1이 큽니다. 밧줄을 자르는 것을 생각하십시오. 당신이 상처를하지 않으면, 당신은 한 조각이 있습니다. 한 번 잘라 두 조각을 제공합니다. 두 번 자르면 세 조각이 나옵니다. 그리고 그것은 파이썬의 str.split (delimiter) 메소드를 사용합니다 :

>>> ''.split(',')       # No cuts
['']
>>> ','.split(',')      # One cut
['', '']
>>> ',,'.split(',')     # Two cuts
['', '', '']

질문 : 문자열에서 줄을 계산하는 더 편리한 방법이 있습니까?

예, 몇 가지 쉬운 방법이 있습니다. 하나 개의 용도는 str.count () 와 다른 용도의 str.splitlines () . 마지막 행에이없는 경우를 제외하고 두 가지 방법 모두 동일한 대답을 제공합니다 \n. 마지막 줄 바꿈이 없으면 str.splitlines 접근 방식으로 정확한 답을 얻을 수 있습니다. 정확한 빠른 기술은 count 방법을 사용하지만 최종 줄 바꿈에 맞게 수정합니다.

>>> data = '''\
Line 1
Line 2
Line 3
Line 4'''

>>> data.count('\n')                               # Inaccurate
3
>>> len(data.splitlines())                         # Accurate, but slow
4
>>> data.count('\n') + (not data.endswith('\n'))   # Accurate and fast
4    

@ Kaz의 질문 : 왜 두 가지 매우 다른 알고리즘이 단일 함수로 분류 되는가?

str.split 의 서명 은 약 20 세이며, 그 시대의 많은 API는 엄격하게 실용적입니다. 완벽하지는 않지만 메소드 서명도 "끔찍하지"않습니다. 대부분의 경우 Guido의 API 디자인 선택은 오랜 시간 동안 테스트되었습니다.

현재 API에는 장점이 없습니다. 다음과 같은 문자열을 고려하십시오.

ps_aux_header  = "USER               PID  %CPU %MEM      VSZ"
patient_header = "name,age,height,weight"

이 문자열을 필드로 나누라는 요청을 받으면 사람들은 동일한 영어 단어 "split"을 사용하여 둘 다 설명하는 경향이 있습니다. fields = line.split() or 와 같은 코드를 읽으라는 요청을 받으면 fields = line.split(',')사람들은 문장을 "필드로 줄을 나누는"것으로 올바르게 해석하는 경향이 있습니다.

Microsoft Excel의 text-to-columns 도구 는 유사한 API를 선택했으며 두 가지 분할 알고리즘을 동일한 도구에 통합했습니다. 사람들은 둘 이상의 알고리즘이 관련되어 있지만 필드 분할을 단일 개념으로 정신적으로 모델링하는 것 같습니다.


28

설명서 에 따르면 단순히 작동하는 방식 인 것 같습니다 .

지정된 구분 기호로 빈 문자열을 분할하면을 반환합니다 [''].

sep가 지정되지 않거나 None 인 경우, 다른 분할 알고리즘이 적용됩니다. 연속 공백 실행은 단일 구분 기호로 간주되며 문자열에 공백이 있거나 공백이 있으면 시작 또는 끝에 빈 문자열이 포함되지 않습니다. 따라서 빈 문자열이나 공백만으로 구성된 문자열을 None 구분 기호로 분리하면 []가 반환됩니다.

따라서 더 명확하게하기 위해이 split()함수는 서로 다른 두 가지 분할 알고리즘을 구현하고 인수의 존재를 사용하여 실행할 알고리즘을 결정합니다. 인수가없는 것보다 인수가없는 것을 최적화 할 수 있기 때문일 수 있습니다. 모르겠어요


4

.split()매개 변수가 없으면 영리하려고합니다. 공백, 탭, 공백, 줄 바꿈 등으로 나뉘며 그 결과 빈 문자열을 모두 건너 뜁니다.

>>> "  fii    fbar \n bopp ".split()
['fii', 'fbar', 'bopp']

본질적으로 .split()매개 변수가 없으면 문자열을 .split()가져 와서 나누는 매개 변수와 달리 문자열에서 단어를 추출하는 데 사용됩니다 .

그것이 차이점의 이유입니다.

그리고 네, 분할하여 라인을 계산하는 것은 효율적인 방법이 아닙니다. 줄 바꿈 수를 세고 문자열이 줄 바꿈으로 끝나지 않으면 줄 바꿈을 추가하십시오.


2

사용 count():

s = "Line 1\nLine2\nLine3"
n_lines = s.count('\n') + 1

4
+ 1은 텍스트가 '\ n'으로 끝나지 않는 경우에만 수행해야합니다.
Lennart Regebro

8
"\ n"으로 끝나는 경우 마지막 줄은 빈 줄입니다. 쓸모는 없지만 여전히 줄로 계산됩니다.
Jakub M.

2
아니. 3 줄의 텍스트를 파일에 쓰고 각 줄을 줄 바꿈으로 끝내면 파일에 3 줄이 들어 있다고 말합니다. 유닉스에서는 텍스트 파일이 항상 줄 바꿈으로 끝나는 것이 가장 좋습니다. 그렇지 않으면 cat file명령 행이 깨져서 Subversion이 불평합니다. vi는 항상 하나를 추가합니다.
user829755

2
>>> print str.split.__doc__
S.split([sep [,maxsplit]]) -> list of strings

Return a list of the words in the string S, using sep as the
delimiter string.  If maxsplit is given, at most maxsplit
splits are done. If sep is not specified or is None, any
whitespace string is a separator and empty strings are removed
from the result.

마지막 문장에 주목하십시오.

줄 수를 세려면 간단히 몇 \n개가 있는지 계산할 수 있습니다 .

line_count = some_string.count('\n') + some_string[-1] != '\n'

마지막 부분은 고려로 끝나지 않는 마지막 줄 필요 \n도 있다고이 수단 불구 Hello, World!하고 Hello, World!\n그렇지 않으면 당신은 간단하게 추가 할 수 있습니다, 같은 라인의 수를 (나를 위해 합리적이다)이 1의 수에 \n.


0

줄 수를 세려면 줄 바꿈 수를 계산하십시오.

n_lines = sum(1 for s in the_string if s == "\n") + 1 # add 1 for last line

편집 :

내장 된 다른 대답count실제로 더 적합합니다.


3
을 사용하는 것 외에도 countbool을 추가 int할 수 있으므로 (실제로 서브 클래스 ) genexp는로 쓸 수 있습니다 sum(s == "\n" for s in the_string).
lvc

지금은 빈 줄만 세고 있습니까?
Thijs van Dien

예, 나는 빈 줄을 버리지 않습니다
Jakub M.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.