Python - write()与writelines()和连接字符串

Abe*_*kon 111 python string file-io python-2.x

所以我正在学习Python.我正在经历课程并遇到一个问题,我必须将一个很多人压缩target.write()成一个单独的write(),同时"\n"在每个用户输入变量(对象write())之间.

我提出了:

nl = "\n"
lines = line1, nl, line2, nl, line3, nl
textdoc.writelines(lines)
Run Code Online (Sandbox Code Playgroud)

如果我尝试做:

textdoc.write(lines)
Run Code Online (Sandbox Code Playgroud)

我收到一个错误.但如果我输入:

textdoc.write(line1 + "\n" + line2 + ....)
Run Code Online (Sandbox Code Playgroud)

然后它工作正常.为什么我无法使用字符串换行,write()但我可以使用它writelines()

Python 2.7当我搜索google时,我发现的大多数资源都是我的头脑,我仍然是一个非常善良的人.

DGH*_*DGH 134

  • writelines 期望一个可迭代的字符串
  • write 期待一个字符串.

line1 + "\n" + line2在将这些字符串传递给它之前将它们合并为一个字符串write.

请注意,如果您有许多行,则可能需要使用"\n".join(list_of_lines).

  • 更具体地说,`writelines`期望可迭代.您可以使用列表,元组或生成器. (44认同)
  • 如果有很多行,为什么要使用`write`而不是`writelines`?Writelines可以更好地执行,因为它不必创建临时连接字符串,只是迭代线. (7认同)
  • Python 中单个字符串也是可迭代的 (2认同)

Jan*_*cke 115

为什么我无法在write()中使用字符串作为换行符,但我可以在writelines()中使用它?

这个想法如下:如果你想写一个字符串,你可以这样做write().如果你有一系列字符串,你可以使用它们全部编写writelines().

write(arg)期望一个字符串作为参数并将其写入文件.如果您提供字符串列表,它将引发异常(顺便说一下,向我们显示错误!).

writelines(arg)期望一个iterable作为参数(一个可迭代对象可以是最一般意义上的元组,列表,字符串或迭代器).迭代器中包含的每个项都应该是一个字符串.你提供了一个字符串元组,所以事情有效.

字符串的性质对两个函数都无关紧要,即它们只是写入文件,无论你提供它们.有趣的是,writelines()它不会自己添加换行符,因此方法名称实际上可能非常混乱.它实际上表现得像一个虚构的方法write_all_of_these_strings(sequence).

接下来是Python中的一种惯用方法,即将字符串列表写入文件,同时将每个字符串保存在自己的行中:

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

这将负责为您关闭文件.该构造'\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)
Run Code Online (Sandbox Code Playgroud)

这使用了生成器表达式并动态创建了以换行符结尾的字符串.writelines()迭代这个字符串序列并写入每个项目.

编辑:您应该注意的另一点:

write()并且readlines()writelines()介绍之前存在.writelines()稍后作为对应方介绍readlines(),以便人们可以轻松地编写刚读取的文件内容readlines():

outfile.writelines(infile.readlines())
Run Code Online (Sandbox Code Playgroud)

真的,这就是为什么writelines这么混乱的名字的主要原因.而且,今天,我们真的不想再使用这种方法了.readlines()writelines()开始写入数据之前,将整个文件读取到计算机的内存中.首先,这可能会浪费时间.为什么不在阅读其他部分时开始编写部分数据?但是,最重要的是,这种方法可能非常耗费内存.在极端情况下,输入文件大于机器的内存,这种方法甚至不起作用.此问题的解决方案是仅使用迭代器.一个工作的例子:

with open('inputfile') as infile:
    with open('outputfile') as outfile:
        for line in infile:
            outfile.write(line)
Run Code Online (Sandbox Code Playgroud)

这会逐行读取输入文件.只要读取一行,该行就会写入输出文件.示意性地说,内存中始终只有一行(与读取/写入方法的情况下整个文件内容在内存中相比).

  • @AbeLinkon:我不支持这个结论.`write()`和`writelines()`基本上是等价的,它们的用法也是个人品味的问题.但是,重要的是要注意,对于一个非常长的字符串列表(称为"行"),编写`f.write('\n'.join(lines))`的效率低于`for l in line: f.write('%s \n'%l)`.在第一种情况下,在写入之前在内存中创建一个全新且非常长的字符串.在第二种情况下,数据是分段编写的. (5认同)
  • 当然你不会做`outf.writelines(inf.readlines())`而是`outf.writelines(inf)`.我们不想再使用的函数是`readlines()`而不是`writelines()`. (5认同)
  • 当我运行它时,f.write('\n'.join(lines))没有添加最后一个nl. (3认同)
  • @moooeeeep:虽然`writelines()`的功能/实现没有任何问题,但正如所解释的那样,它的语义并不理想.这就是我从未使用过它的原因.我从来没有错过它. (2认同)
  • @AbeLinkon - 也许你应该考虑接受这个答案,它明显优于你最初接受的答案 (2认同)