จะใช้ newline '\ n' ใน f-string เพื่อจัดรูปแบบเอาต์พุตใน Python 3.6 ได้อย่างไร


133

ฉันต้องการทราบวิธีจัดรูปแบบเคสนี้ด้วยวิธี Pythonic ด้วย f-strings:

names = ['Adam', 'Bob', 'Cyril']
text = f"Winners are:\n{'\n'.join(names)}"
print(text)

ปัญหาคือ'\'ไม่สามารถใช้ภายใน{...}ส่วนนิพจน์ของ f-string ผลลัพธ์ที่คาดหวัง:

Winners are:
Adam
Bob
Cyril

11
f"Winners are:\n{chr(10).join(names)}"
Wim

คำตอบ:


143

คุณทำไม่ได้ backslashes ไม่สามารถปรากฏอยู่ภายในวงเล็บปีกกา{}; การทำเช่นนั้นส่งผลให้SyntaxError:

>>> f'{\}'
SyntaxError: f-string expression part cannot include a backslash

ระบุไว้ในPEPสำหรับ f-strings:

แบ็กสแลชอาจไม่ปรากฏในส่วนนิพจน์ของ f-strings [... ]

ทางเลือกหนึ่งคือการยอมรับ'\n'ชื่อและจากนั้นก็.joinอยู่ในf-string; นั่นคือโดยไม่ต้องใช้ตัวอักษร:

names = ['Adam', 'Bob', 'Cyril']
nl = '\n'
text = f"Winners are:{nl}{nl.join(names)}"
print(text)

ผลลัพธ์ใน:

Winners are:
Adam
Bob
Cyril

อีกทางเลือกหนึ่งตามที่ @wim ระบุคือใช้chr(10)เพื่อรับ\nคืนจากนั้นเข้าร่วมที่นั่นf"Winners are:\n{chr(10).join(names)}"

แน่นอนอีกอย่างคือต้องทำ'\n'.joinไว้ก่อนแล้วจึงเพิ่มชื่อตามนั้น:

n = "\n".join(names)
text = f"Winners are:\n{n}"

ซึ่งให้ผลลัพธ์เดียวกัน

บันทึก:

นี่คือหนึ่งในความแตกต่างเล็กน้อยระหว่างf-strings และstr.format. ในช่วงหลังคุณสามารถใช้เครื่องหมายวรรคตอนที่กำหนดให้คลายการบีบอัดคำสั่งแปลกประหลาดที่เกี่ยวข้องซึ่งมีคีย์เหล่านี้

>>> "{\\} {*}".format(**{"\\": 'Hello', "*": 'World!'})
"Hello World!"

(โปรดอย่าทำเช่นนี้)

ในอดีตไม่อนุญาตให้ใช้เครื่องหมายวรรคตอนเนื่องจากคุณไม่มีตัวระบุที่ใช้


นอกเหนือ: ฉันจะเลือกprintหรือformatตามที่คำตอบอื่นแนะนำเป็นทางเลือก ตัวเลือกที่ฉันให้ไว้จะใช้ได้ก็ต่อเมื่อคุณต้องใช้ f-strings ด้วยเหตุผลบางประการ

เพียงเพราะมีบางอย่างใหม่ไม่ได้หมายความว่าคุณควรลองทำทุกอย่างกับมัน ;-)


ไม่สมเหตุสมผลกับฉัน: nl = '\n' text = f"Winners are:{nl}". ใช้: text = f "ผู้ชนะคือ: \ n"
Timo

@Timo OP จำเป็นต้องjoinเปิด\nในสตริงรูปแบบโดยเฉพาะในนิพจน์ฝังตัว
Dimitris Fasarakis Hilliard

56

คุณไม่จำเป็นต้องใช้ f-strings หรือฟอร์แมตอื่น ๆ เพื่อพิมพ์รายการสตริงที่มีตัวคั่น เพียงใช้sepอาร์กิวเมนต์คำหลักเพื่อprint():

names = ['Adam', 'Bob', 'Cyril']
print('Winners are:', *names, sep='\n')

เอาท์พุต:

Winners are:
Adam
Bob
Cyril

ที่กล่าวว่าการใช้str.join()/str.format() here จะง่ายกว่าและอ่านง่ายกว่าวิธีแก้ปัญหา f-string ใด ๆ :

print('\n'.join(['Winners are:', *names]))
print('Winners are:\n{}'.format('\n'.join(names)))

13
คำตอบที่ดีที่สุดจนถึงตอนนี้ ฉันจะใช้ดาวเปิดออกในฟังก์ชั่นการพิมพ์ตลอดเวลาวันนี้จะได้ดูภายในวัตถุบางอย่างเช่นหรือprint(*dir(some_object), sep='\n') print(*vars(some_object), sep='\n')
Rick สนับสนุน Monica

1
คุณจะทำอย่างไรถ้าคุณไม่ต้องการพิมพ์รายการโดยตรงเช่นถ้าคุณส่งไปให้คนตัดไม้?
บ๊อบ

1
@bob: จากนั้นใช้str.join(): text = '\n'.join(['Winners are:', *names]). BTW print()สามารถใช้เพื่อเขียนไปยังไฟล์ใดก็ได้ (ระบุด้วยfileอาร์กิวเมนต์sys.stdoutโดยค่าเริ่มต้น)
Eugene Yarmash

11

คุณไม่สามารถใช้แบ็กสแลชใน f-strings ได้ตามที่คนอื่นพูด แต่คุณสามารถใช้สิ่งนี้ได้os.linesep(แม้ว่าจะทราบว่าสิ่งนี้จะไม่สามารถใช้ได้\nกับทุกแพลตฟอร์มและไม่แนะนำให้ใช้เว้นแต่จะอ่าน / เขียนไฟล์ไบนารีดูความคิดเห็นของ Rick ):

>>> import os
>>> names = ['Adam', 'Bob', 'Cyril']
>>> print(f"Winners are:\n{os.linesep.join(names)}")
Winners are:
Adam
Bob
Cyril 

หรือบางทีอาจจะในทางที่สามารถอ่านได้น้อยลง แต่รับประกันว่าจะ\nมีchr():

>>> print(f"Winners are:\n{chr(10).join(names)}")
Winners are:
Adam
Bob
Cyril

2
ไม่ใช่ผม แต่ใช้os.linesepเป็นไม่ได้เป็นความคิดที่ดีเมื่อเขียนข้อความ
Rick สนับสนุน Monica

1
@RickTeachey ฉันได้เพิ่มข้อแม้ในวงเล็บแล้วและแนะนำแนวทางอื่น อย่างไรก็ตาม OP กำลังพิมพ์ไปยังหน้าจอไม่ได้เขียนไปยังไฟล์ที่เปิดในโหมดข้อความ
Chris_Rands

ฉันไม่คิดว่ามันสำคัญ os.linesepเป็นเพียงสำหรับการอ่านหรือการอ่านและการเขียนในโหมดไบนารี ฉันรู้ว่ามันจะได้ผลเหมือนกันในกรณีนี้ แต่มันเป็นนิสัยที่ไม่ดีในการเริ่มต้น แต่อีกครั้ง: ฉันไม่ได้ลงคะแนน ข้อแม้ดีพอสำหรับฉัน :)
Rick สนับสนุน Monica

8

คำตอบอื่น ๆ ให้แนวคิดในการใส่อักขระขึ้นบรรทัดใหม่ลงในฟิลด์ f-string อย่างไรก็ตามฉันขอโต้แย้งว่าสำหรับตัวอย่างที่ OP ให้มา (ซึ่งอาจบ่งบอกถึงกรณีการใช้งานจริงของ OP หรือไม่ก็ได้) ไม่ควรนำแนวคิดเหล่านี้ไปใช้จริง

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

f"Winners are:\n{'\n'.join(names)}"

... หรือสิ่งนี้:

newline = '\n'
f"Winners are:\n{newline.join(names)}"

... หรือสิ่งนี้:

"Winners are:\n{chr(10).join(names)}"

เทียบกับสิ่งนี้:

"Winners are:\n{}".format('\n'.join(names))

วิธีสุดท้ายอย่างน้อยที่สุดก็สามารถอ่านได้หากไม่เป็นเช่นนั้น

กล่าวโดยย่อ: อย่าใช้ค้อนเมื่อคุณต้องการไขควงเพียงเพราะคุณมีอันใหม่มันวาว โค้ดถูกอ่านบ่อยกว่าที่เขียน

สำหรับกรณีการใช้งานอื่น ๆ ใช่เป็นไปได้ว่าchr(10)แนวคิดหรือnewlineแนวคิดอาจเหมาะสม แต่ไม่ใช่สำหรับคนที่ให้


9
ความสามารถในการอ่านเป็นเรื่องส่วนตัว :) ... การฝึกฝนแบบเก่าเหมาะกับผู้ที่มีทักษะและสามารถอ่านได้มากกว่าในบางกรณี แต่แทบจะไม่เป็นที่รู้จักสำหรับ noobs และด้วยเหตุนี้จึงไม่สามารถอ่านได้สำหรับพวกเขา ขออภัยสำหรับมุมมองทางปรัชญา
malmed

2
ความสามารถในการอ่าน @malmed โดยทั่วไปไม่ใช่เรื่องส่วนตัว ไม่แน่นอนในกรณีนี้ แต่ก็ไม่คุ้มที่จะโต้เถียงเกี่ยวกับความยาว
Rick สนับสนุน Monica

1
@malmed คุณกำลังขวาที่อ่านง่ายคือ "อัตนัย" ในแง่ที่ว่ามันเป็นสุวินัยโดยประสบการณ์ก่อน แต่เนื่องจากสมองและประสาทสัมผัสของเรามีข้อ จำกัด ความสามารถในการอ่านจึงสามารถวัดได้ในแง่ของความง่ายในการสแกนข้อความที่เกี่ยวข้องสมองของมนุษย์มีแนวโน้มที่จะจับคู่รูปแบบได้อย่างถูกต้องบ่อยเพียงใดมันบ่งบอกถึงการคาดเดาของสมองเกี่ยวกับสิ่งอื่น ๆ ได้อย่างถูกต้องเพียงใด รหัส (รวมถึงจุดเริ่มต้นของคำสั่ง / บรรทัดที่บอกเป็นนัยว่าจุดจบจะเป็นอย่างไร) และมือใหม่จะอ่านได้ง่ายเพียงใด
mtraceur
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.