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在您的示例中不是字符串。它是由六个字符串组成的元组。
巴绍(Bachsau)

Answers:


147
  • writelines 期待字符串的迭代
  • write 需要一个字符串。

line1 + "\n" + line2将这些字符串合并到一个字符串中,然后再传递给write

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


50
更具体地说,writelines期望是可迭代的。您可以使用列表,元组或生成器。
Mark Ransom 2012年

谢谢您的回答,先生。我假设使用名称(list_of_lines)列出一个字符串列表,然后传递给.join(list)?
AbeLinkon 2012年

9
如果您有很多行,为什么要使用write而不是writelines?Writelines可能会更好地执行,因为它不必创建临时的串联字符串,而只需遍历行即可。
Bouke 2014年


1
单个字符串在Python中也是可迭代的
natbusa

122

为什么我不能在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))

这将为您关闭文件。该构造'\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)

这将逐行读取输入文件。读取一行后,该行即被写入输出文件。从概念上讲,内存中始终只有一行(相比之下,在采用读取行/写入行方法的情况下,整个文件内容都在内存中)。


5
@AbeLinkon:我不支持这个结论。write()并且writelines()基本上等同和它们的用法也是个人品味的问题。但是,请务必注意,对于非常长的字符串列表(称为lines),编写效率要f.write('\n'.join(lines))低于for l in line: f.write('%s\n' % l)。在第一种情况下,在写入之前会在内存中创建一个全新且非常长的字符串。在第二种情况下,数据是分段写入的。
Jan-Philip Gehrcke博士2012年

3
当我运行它时,f.write('\ n'.join(lines))没有添加最后一个nl。
Jiminion

5
当然你不会这么做outf.writelines(inf.readlines()),而是outf.writelines(inf)。我们不想再使用的功能readlines()不是writelines()
moooeeeep

2
@moooeeeep:尽管的功能/实现没有错,但writelines()正如所解释的那样,其语义并不理想。这就是为什么我从未使用过它的原因。而且我从未错过。
Jan-Philip Gehrcke博士,2015年

2
@AbeLinkon -也许你应该考虑接受这个答案,它显然比最初接受了一个更好的
彼得· -代表莫妮卡

-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

习德(Zed Shaw)的书中的练习16?您可以使用转义符,如下所示:

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

很弱的解决方案。如果您想以这种方式连接几行,则应按以下步骤进行:" \n ".join((line1, line2, line3))
巴绍(Bachsau)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.