web-dev-qa-db-ja.com

Python - write()とwritelines()および連結ストリング

私はPythonを学んでいます。各ユーザー入力変数(target.write()のオブジェクト)の間に"\n"を入れながら、レッスンを進めていて、非常に多くのwrite()を単一の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で検索したとき、私はまだ素人です。

98
AbeLinkon
  • writelinesは文字列のイテラブルを期待しています
  • writeは単一の文字列を期待します。

line1 + "\n" + line2は、それらの文字列をwriteに渡す前にそれらを単一の文字列にマージします。

あなたが多くの行を持っているなら、あなたは"\n".join(list_of_lines)を使いたくなるかもしれないことに注意してください。

117
DGH

なぜ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()は、この一連の文字列を繰り返し処理してすべての項目を書き込みます。

編集:あなたが知っておくべきもう一つのポイント:

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アプローチの場合はファイルの内容全体がメモリ内にあるのに対して)。

107