Python-write()対writelines()および連結された文字列


124

私はPythonを学んでいます。私はレッスンを進めていて、各ユーザー入力変数の間に(のオブジェクト)を持っている間に、非常に多くtarget.write()を単一のに圧縮しなければならないという問題に遭遇しました。write()"\n"write()

私は思いついた:

nl = "\n"
lines = line1, nl, line2, nl, line3, nl
textdoc.writelines(lines)

私がやろうとした場合:

textdoc.write(lines)

エラーが発生します。しかし、私がタイプすると:

textdoc.write(line1 + "\n" + line2 + ....)

その後、正常に動作します。で改行に文字列を使用できないのになぜwrite()それを使用できるのwritelines()ですか?

Python 2.7 googleで検索したところ、私が見つけたほとんどのリソースは頭上にありましたが、私はまだ素人です。


linesあなたの例では文字列ではありません。6つの文字列からなるタプルです。
Bachsau

回答:


147
  • writelines 反復可能な文字列を期待します
  • write 単一の文字列が必要です。

line1 + "\n" + line2に渡す前に、これらの文字列を1つの文字列にマージしwriteます。

行数が多い場合は、を使用することもできます"\n".join(list_of_lines)


50
より具体的にwritelinesは、反復可能であることを期待しています。リスト、タプル、またはジェネレーターを使用できます。
Mark Ransom 2012

お返事ありがとうございます。名前(list_of_lines)で、文字列のリストを作成して.join(list)に渡す必要があると想定していますか?
AbeLinkon 2012

9
多くの行がwriteあるwritelines場合、代わりになぜ使用する必要がありますか?一時的に連結された文字列を作成する必要がなく、行を繰り返すだけなので、writelinesの方がパフォーマンスが優れている可能性があります。
Bouke


1
単一の文字列はPythonでも反復可能です
natbusa

122

write()の改行に文字列を使用できないのに、writelines()で使用できるのはなぜですか?

アイデアは次のとおりですwrite()。単一の文字列を記述したい場合は、でこれを行うことができます。文字列のシーケンスがある場合は、を使用してそれらをすべて書き込むことができますwritelines()

write(arg)引数として文字列を期待し、それをファイルに書き込みます。文字列のリストを提供すると、例外が発生します(ちなみに、エラーが表示されます!)。

writelines(arg)引数としてイテラブルを期待します(イテラブルオブジェクトは、タプル、リスト、文字列、または最も一般的な意味でのイテレータにすることができます)。イテレーターに含まれる各項目は、ストリングであることが期待されています。文字列のタプルはあなたが提供したものなので、うまくいきました。

文字列の性質は、どちらの関数にも関係ありません。つまり、文字列は、ユーザーが指定したものをファイルに書き込むだけです。興味深い部分は、writelines()それ自体で改行文字を追加しないことです。そのため、メソッド名は実際にはかなり混乱する可能性があります。実際にはと呼ばれる架空のメソッドのように動作しwrite_all_of_these_strings(sequence)ます。

以下は、Pythonでの慣用的な方法であり、文字列のリストをファイルに書き込みながら、各文字列を独自の行に保持しています。

lines = ['line1', 'line2']
with open('filename.txt', 'w') as f:
    f.write('\n'.join(lines))

これにより、ファイルが閉じられます。構成'\n'.join(lines)はリスト内の文字列を連結(接続)linesし、文字 '\ n'を接着剤として使用します。+演算子を使用するよりも効率的です。

同じlinesシーケンスから始まり、同じ出力で終わりますが、以下を使用していwritelines()ます:

lines = ['line1', 'line2']
with open('filename.txt', 'w') as f:
    f.writelines("%s\n" % l for l in lines)

これはジェネレータ式を利用し、改行で終了する文字列を動的に作成します。writelines()この一連の文字列を反復処理し、すべてのアイテムを書き込みます。

編集:注意すべきもう1つのポイント:

write()と導入さreadlines()れる前writelines()に存在しました。writelines()はの対応物として後で紹介されたreadlines()ので、単にを介して読み取られたファイルの内容を簡単に書き込むことができましたreadlines()

outfile.writelines(infile.readlines())

本当に、これがそのwritelinesような紛らわしい名前を持っている主な理由です。また、今日では、このメソッドを使用する必要はありません。データの書き込みを開始するreadlines()前に、ファイル全体をマシンのメモリに読み取りwritelines()ます。まず第一に、これは時間を浪費するかもしれません。他の部分を読みながら、データの一部を書き始めませんか?しかし、最も重要なのは、このアプローチは非常に多くのメモリを消費する可能性があることです。極端なシナリオでは、入力ファイルがマシンのメモリよりも大きい場合、このアプローチは機能しません。この問題の解決策は、反復子のみを使用することです。実際の例:

with open('inputfile') as infile:
    with open('outputfile') as outfile:
        for line in infile:
            outfile.write(line)

これにより、入力ファイルが1行ずつ読み込まれます。1行が読み取られるとすぐに、この行は出力ファイルに書き込まれます。概略的に言うと、メモリ内には常に1行しかありません(readlines / writelinesアプローチの場合、ファイルコンテンツ全体がメモリ内にあるのと比較して)。


5
@AbeLinkon:私はこの結論を支持しません。write()writelines()基本的に同等であり、それらの使用法も個人的な好みの問題です。ただし、文字列のリストが非常に長い(と呼ばれるlines)場合、を書くf.write('\n'.join(lines))よりも効率が悪いことに注意することが重要ですfor l in line: f.write('%s\n' % l)。最初のケースでは、完全に新しく非常に長い文字列が書き込まれる前にメモリに作成されます。2番目のケースでは、データは断片的に書き込まれます。
Jan-Philip Gehrcke博士2012

3
f.write( '\ n'.join(lines))は、実行したときに最後のnlを追加しませんでした。
Jiminion 2013

5
もちろん、あなたはしないだろうoutf.writelines(inf.readlines())けど、むしろoutf.writelines(inf)。もう使いたくない機能はありませreadlines()writelines()
moooeeeep 2015年

2
@moooeeeep:の機能/実装に問題はありませんがwritelines()、そのセマンティクスは、説明したように、理想的とは言えません。これが私がこれを使用したことがない理由です。そして、私はそれを逃したことはありません。
Jan-Philip Gehrcke博士、2015

2
@AbeLinkon-この回答を受け入れることを検討する必要があるかもしれません。最初に受け入れた回答よりも明らかに優れています
Peter M.-

-4

リストを保存してロードするだけの場合は、Pickleを試してください

ピクルセービング:

with open("yourFile","wb")as file:
 pickle.dump(YourList,file)

と読み込み:

with open("yourFile","rb")as file:
 YourList=pickle.load(file)

-5

実際、問題は変数の「行」が悪いことだと思います。行をタプルとして定義しましたが、write()には文字列が必要だと思います。変更する必要があるのは、コンマをプラス(+)にすることだけです。

nl = "\n"
lines = line1+nl+line2+nl+line3+nl
textdoc.writelines(lines)

うまくいくはずです。


-5

ゼド・ショーの本の演習16?次のようにエスケープ文字を使用できます。

paragraph1 = "%s \n %s \n %s \n" % (line1, line2, line3)
target.write(paragraph1)
target.close()

非常に弱いソリューション。この方法で複数の行を連結したい場合は、次のようにする必要があります" \n ".join((line1, line2, line3))
バクサウ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.