Python - write () เทียบกับ wrelines () และสตริงที่ต่อกัน


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

คำตอบ:


147
  • writelines คาดว่าสตริงที่สามารถทำซ้ำได้
  • write คาดว่าจะมีสตริงเดียว

line1 + "\n" + line2writeผสานสตริงเหล่านั้นเข้าด้วยกันเป็นสายเดียวก่อนที่จะผ่านไปยัง

"\n".join(list_of_lines)หมายเหตุว่าถ้าคุณมีหลายสายคุณอาจต้องการที่จะใช้


50
โดยเฉพาะอย่างยิ่งwritelinesคาดว่าจะสามารถทำซ้ำได้ คุณสามารถใช้รายการทูเพิลหรือเครื่องกำเนิดไฟฟ้า
Mark Ransom

ขอบคุณสำหรับคำตอบครับ ฉันสมมติโดยใช้ชื่อ (list_of_lines) ว่าฉันควรสร้างรายการสตริงและส่งต่อไปยัง. เข้าร่วม (รายการ)?
AbeLinkon

9
ทำไมคุณควรใช้writeแทนwritelinesถ้าคุณมีหลายบรรทัด? Writelines สามารถทำงานได้ดีกว่าเนื่องจากไม่จำเป็นต้องสร้างสตริงที่ต่อกันชั่วคราวเพียงแค่วนซ้ำบนบรรทัด
Bouke

@ hBy2Py: ตรงกันข้าม: stackoverflow.com/a/6165711/281545
Mr_and_Mrs_D

1
สตริงเดียวสามารถทำซ้ำได้ใน Python
natbusa

123

เหตุใดฉันจึงไม่สามารถใช้สตริงสำหรับขึ้นบรรทัดใหม่ในการเขียน () แต่ฉันสามารถใช้ในการเขียน ()

ความคิดคือต่อไปนี้: write()ถ้าคุณต้องการที่จะเขียนสายเดียวที่คุณสามารถทำเช่นนี้กับ writelines()ถ้าคุณมีลำดับของสตริงที่คุณสามารถเขียนพวกเขาทั้งหมดที่ใช้

write(arg)คาดว่าสตริงเป็นอาร์กิวเมนต์และเขียนลงในไฟล์ หากคุณระบุรายการสตริงจะทำให้เกิดข้อยกเว้น (โดยวิธีนี้แสดงข้อผิดพลาดให้เราทราบ!)

writelines(arg)คาดว่าจะสามารถทำซ้ำได้เป็นอาร์กิวเมนต์ (อ็อบเจ็กต์ที่ทำซ้ำได้อาจเป็นทูเพิลรายการสตริงหรือตัววนซ้ำในความหมายทั่วไป) แต่ละรายการที่อยู่ในตัววนซ้ำคาดว่าจะเป็นสตริง Tuple ของสตริงคือสิ่งที่คุณให้มาสิ่งต่าง ๆ ก็ใช้ได้ผล

ลักษณะของสตริงไม่สำคัญกับทั้งสองฟังก์ชันกล่าวคือเพียงแค่เขียนไปยังไฟล์สิ่งที่คุณให้มา ส่วนที่น่าสนใจคือ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)ในกรณีแรกสตริงใหม่ทั้งหมดและยาวมากจะถูกสร้างขึ้นในหน่วยความจำก่อนที่จะเขียนมัน ในกรณีที่สองข้อมูลจะถูกเขียนอย่างชาญฉลาด
Dr.Jan-Philip Gehrcke

3
f.write ('\ n'.join (เส้น)) ไม่ได้เพิ่ม nl สุดท้ายเมื่อฉันเรียกใช้
Jiminion

5
แน่นอนคุณจะไม่ทำแต่outf.writelines(inf.readlines()) outf.writelines(inf)ฟังก์ชั่นที่เราไม่ต้องการที่จะใช้อีกต่อไปไม่ได้readlines() writelines()
moooeeeep

2
@moooeeeep: แม้ว่าจะไม่มีอะไรผิดปกติกับการทำงาน / การนำไปใช้writelines()แต่ความหมายของมันก็เป็นไปตามที่อธิบายไว้น้อยกว่าอุดมคติ นี่คือเหตุผลที่ฉันไม่เคยใช้มัน และฉันไม่เคยพลาดเลย
Dr. Jan-Philip Gehrcke

2
@AbeLinkon - บางทีคุณควรพิจารณายอมรับคำตอบนี้จะดีกว่าที่คุณยอมรับในตอนแรกอย่างชัดเจน
Peter M. - ย่อมาจาก Monica

-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 จากหนังสือของ Zed Shaw? คุณสามารถใช้อักขระหลีกได้ดังนี้:

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

วิธีแก้ปัญหาที่อ่อนแอมาก หากคุณต้องการ concatenate " \n ".join((line1, line2, line3))หลายสายในลักษณะนี้ที่คุณควรทำเช่นนี้
Bachsau
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.