Python で空の文字列を分割する場合、split() は空のリストを返すのに、split('\n') は [''] を返すのはなぜですか? 質問する

Python で空の文字列を分割する場合、split() は空のリストを返すのに、split('\n') は [''] を返すのはなぜですか? 質問する

split('\n')1 つの文字列で行を取得するために を使用していますが、 は''.split()空のリストを返し[]''.split('\n')は を返します['']。このような違いには何か特別な理由があるのでしょうか?

文字列内の行数をカウントするより便利な方法はありますか?

ベストアンサー1

質問: 1 つの文字列で行を取得するために を使用しておりsplit('\n')、 は''.split()空のリストを返し[]''.split('\n')は を返すことがわかりました['']

str.split()このメソッドには 2 つのアルゴリズムがあります。引数が指定されていない場合は、空白文字の繰り返しで分割されます。ただし、引数が指定されている場合は、繰り返しのない単一の区切り文字として扱われます。

空の文字列を分割する場合、最初のモード (引数なし) では、空白が消費され、結果リストに入れる値がないため、空のリストが返されます。

対照的に、2 番目のモード ( などの引数を使用\n) では、最初の空のフィールドが生成されます。 と記述した場合'\n'.split('\n')、2 つのフィールドが生成されます (1 つの分割により、2 つの半分が生成されます)。

質問: このような違いには何か特別な理由があるのでしょうか?

この最初のモードは、データがさまざまな量の空白を含む列に配置されている場合に便利です。例:

>>> 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']

2番目のモードは、次のような区切りデータに便利です。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 つ多いことに注意してください。ロープを切ることを考えてみてください。切断しなければ、1 つのピースになります。1 つ切断すると、2 つのピースになります。2 つ切断すると、3 つのピースになります。Python の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 からの質問: 一体なぜ 2 つの非常に異なるアルゴリズムが 1 つの関数に押し込められているのでしょうか?

のシグネチャは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()fields = line.split(',')人々はこれらの文を「行をフィールドに分割する」と正しく解釈する傾向があります。

Microsoft Excelのテキストを列に分割するツール同様の API を選択し、両方の分割アルゴリズムを同じツールに組み込んでいます。複数のアルゴリズムが関係しているにもかかわらず、人々はフィールド分割を単一の概念として精神的にモデル化しているようです。

おすすめ記事