ทำไม% s ถึงดีกว่า + สำหรับการต่อข้อมูล


88

ฉันเข้าใจว่าเราควรใช้%sเพื่อเชื่อมสตริงเข้าด้วยกันแทนที่จะเป็น+Python

ฉันสามารถทำสิ่งใดก็ได้:

hello = "hello"
world = "world"

print hello + " " + world
print "%s %s" % (hello, world)
print "{} {}".format(hello, world)
print ' '.join([hello, world])

แต่ทำไมฉันถึงควรใช้สิ่งอื่นนอกเหนือจาก+? การเขียนเรียงต่อกันด้วยวิธีง่าย+กว่าทำได้เร็วกว่า จากนั้นหากคุณดูที่สตริงการจัดรูปแบบคุณจะระบุประเภทเช่น%sและ%dและ ฉันเข้าใจว่ามันจะดีกว่าหากจะระบุประเภทให้ชัดเจน

แต่ฉันอ่านแล้วว่า+ควรหลีกเลี่ยงการใช้การต่อข้อมูลแบบเรียงต่อกันแม้ว่าจะพิมพ์ง่ายกว่าก็ตาม มีเหตุผลที่ชัดเจนที่ควรรวมสตริงเข้าด้วยกันด้วยวิธีใดวิธีหนึ่งเหล่านี้หรือไม่?


29
ใครบอกคุณว่าดีกว่า
yannis

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

ฉันโฟกัสคำถามไปที่เพียงแค่ไพ ธ อน (แม้ว่าฉันไม่ใช่คนไพ ธ อนและอาจมีข้อบกพร่องในโค้ด) กรุณาตรวจสอบให้แน่ใจว่านี้เป็นคำถามที่คุณจะถามให้ปรับปรุงที่เหมาะสมใด ๆ และพิจารณาขอให้แตกต่างกันคำถามถ้าคุณมีความสนใจใน C หรือ Java

12
และตอนนี้เรามีสตริง f ที่เหนือกว่า ! มีการอ่านของการเรียงต่อกันตั้งแต่ตัวแปรจะเห็นที่พวกเขาเกิดขึ้นในสตริงและจะเร็วกว่าprint(f"{hello} {world}") str.format
Enrico Borba

คำตอบ:


88
  1. การอ่าน ไวยากรณ์สตริงรูปแบบสามารถอ่านได้มากขึ้นเนื่องจากแยกสไตล์ออกจากข้อมูล นอกจากนี้ใน Python %sไวยากรณ์จะบังคับstrชนิดที่ไม่ให้เป็นstrเช่นนั้นโดยอัตโนมัติ ในขณะที่การเรียงต่อกันเท่านั้นทำงานร่วมกับstrและคุณไม่สามารถเชื่อมกับstrint

  2. ประสิทธิภาพ. ใน Python strนั้นไม่เปลี่ยนรูปดังนั้นสตริงซ้ายและขวาจะต้องคัดลอกลงในสายอักขระใหม่สำหรับการต่อข้อมูลทุกคู่ หากคุณต่อสตริงสี่ความยาว 10 คุณจะคัดลอก (10 + 10) + ((10 + 10) +10) + (((10 + 10) +10) +10) = 90 ตัวอักษรแทนที่จะเป็นแค่ 40 ตัวละคร และสิ่งต่าง ๆ จะแย่ลงเป็นสองเท่าเมื่อจำนวนและขนาดของสตริงเพิ่มขึ้น Java ปรับกรณีนี้ให้เหมาะสมบางครั้งโดยเปลี่ยนชุดการต่อข้อมูลที่จะใช้StringBuilderแต่ CPython ไม่ต้องการ

  3. สำหรับบางกรณีการใช้งานไลบรารีการบันทึกมี API ที่ใช้สตริงรูปแบบเพื่อสร้างสตริงรายการบันทึกอย่างเกียจคร้าน ( logging.info("blah: %s", 4)) สิ่งนี้ดีมากสำหรับประสิทธิภาพที่ดีขึ้นถ้าไลบรารีการบันทึกตัดสินใจว่ารายการบันทึกปัจจุบันจะถูกยกเลิกโดยตัวกรองบันทึกดังนั้นจึงไม่จำเป็นต้องจัดรูปแบบสตริง


31
คุณมีแหล่งข้อมูลทางวิทยาศาสตร์หรือเชิงประจักษ์สำหรับ # 1 หรือไม่? เพราะฉันคิดว่ามันอ่านได้น้อยกว่ามาก (โดยเฉพาะอย่างยิ่งที่มีข้อโต้แย้งมากกว่า 2 หรือสามข้อ)
Lovis

4
@ L.Möller: ฉันไม่แน่ใจว่าแหล่งที่มาแบบไหนที่คุณคาดหวังจากประสบการณ์ส่วนตัว (ความสะดวกในการอ่าน) แต่ถ้าคุณต้องการเหตุผลของฉัน: 1)% s ต้องการอักขระพิเศษ 2 ตัวต่อตัวยึดเทียบกับ + ต้องการ อย่างน้อย 4 (หรือ 8 ถ้าคุณทำตาม PEP8, 13 ถ้าคุณถูกบังคับ), 2)% s อยู่ในสตริงเดียวดังนั้นจึงง่ายต่อการแยกวิเคราะห์ทางสายตาด้วย + คุณมีส่วนที่เคลื่อนไหวได้มากขึ้น: ปิดสตริงตัวดำเนินการตัวแปร , โอเปอเรเตอร์, สตริงเปิด, 3) การระบายสีไวยากรณ์% s มีหนึ่งสีสำหรับแต่ละฟังก์ชั่น: สตริงและตัวยึดตำแหน่งด้วย + คุณจะได้รับสามสี: สตริงตัวดำเนินการและการระบายสีตัวแปร
Lie Ryan

4
@ L.Möller: 4) ฉันมีตัวเลือกที่จะใส่สตริงการจัดรูปแบบอีกต่อไปในตัวแปรหรือพจนานุกรมห่างจากที่ต้องจัดรูปแบบที่จะต้องทำ 5) สตริงรูปแบบสามารถระบุผู้ใช้จากไฟล์ config, args คำสั่งหรือฐานข้อมูล ไม่สามารถพูดแบบเดียวกันได้กับการต่อข้อมูล แต่ใช่ฉันจะไม่ใช้% s เมื่อฉันมีสิ่งต่าง ๆ มากกว่า 4-5 รายการที่จะแก้ไขแทนฉันจะใช้ตัวแปรของ% (varname) หรือ "{foo}". format () ใน Python ฉันคิดว่าชื่อที่ชัดเจนช่วยเพิ่มความสามารถในการอ่านสำหรับสตริงการจัดรูปแบบที่ยาวขึ้นพร้อมกับตัวแปร interpolated มากมาย
Lie Ryan

2
ฉันไม่รู้ว่า "จริง" คืออะไรทำไมฉันถามว่าคุณมีหลักฐาน :-) เห็นด้วยกับความคิดเห็นที่สองของคุณจริงๆ
Lovis

6
ฉันพบข้อสงสัย # 2 - คุณมีเอกสารหลักฐานหรือไม่ ฉันไม่ยิ่งคุ้นเคยกับ Java แต่ใน C # เรียงต่อกันจะเร็วกว่าการแก้ไขสตริง ฉันเห็นด้วยอย่างสมบูรณ์กับ # 1 และเชื่อถือได้อย่างแท้จริงสำหรับการตัดสินใจว่าจะใช้เมื่อใด แต่คุณต้องจำการแก้ไขต้องใช้จำนวนของการแยกสตริงและความซับซ้อนซึ่งการต่อข้อมูลไม่จำเป็นต้องมีสิ่งใด
Jimmy Hoffa

48

ฉันเป็นคนเดียวที่อ่านจากซ้ายไปขวา?

สำหรับฉันการใช้%sเป็นเหมือนการฟังวิทยากรชาวเยอรมันที่ฉันต้องรอจนกว่าจะสิ้นสุดประโยคยาวมากเพื่อฟังว่าคำกริยาคืออะไร

ข้อใดต่อไปนี้ที่ชัดเจนยิ่งขึ้น

"your %s is in the %s" % (object, location)

หรือ

"your " + object + " is in the " + location  

17
เห็นได้ชัดว่านี่เป็นอัตวิสัยเนื่องจากฉันพบว่าคนแรกอ่านได้ง่ายขึ้นและเขียนและแก้ไขได้ง่ายขึ้น ส่วนที่สองแทรกข้อความที่มีรหัสซึ่งปิดกั้นทั้งสองและเพิ่มสัญญาณรบกวน ตัวอย่างเช่นมันง่ายที่จะทำให้ช่องว่างผิดในวินาที
JacquesB

5
@JacquesB ฉันคิดว่าสมองของคุณคุ้นเคยกับรูปแบบนี้มากจนคุณกระโดดไปที่วงเล็บแล้วเปลี่ยนคำทันที ในทางเทคนิคแล้วมันไม่ใช่การอ่านจากซ้ายไปขวา แต่มันก็ใช้ได้ดี ฉันพบว่าฉันก็ทำเช่นนั้นดังนั้นใช่ 1 ง่ายต่อการอ่านเพราะฉันรู้ว่าฉันต้องจัดการกับปัญหาระยะห่างที่โง่ก่อนและหลังราคาในวินาทีและนั่นก็ช้าที่จะทำงานด้วย
เนลสัน

3
หลังจากnผ่านไปหลายสิบปีจิตใจของฉันก็เป็นแบบนั้นเหมือนกัน ;-) แต่ฉันยังคงยืนหยัดอยู่กับคำตอบข้อที่สองชัดเจนและอ่านง่ายกว่าดังนั้นเพื่อรักษา และนั่นจะยิ่งชัดเจนยิ่งขึ้นเมื่อคุณมีพารามิเตอร์มากขึ้น ในท้ายที่สุดถ้าเป็นการแสดงของชายคนหนึ่งไปกับสิ่งที่คุณคุ้นเคยและคุ้นเคย ถ้ามันเป็นความพยายามของทีมบังคับใช้ความสอดคล้องและการตรวจสอบรหัส; ผู้คนสามารถคุ้นเคยกับทั้ง
Mawg

4
คนแรกอ่านได้ง่ายกว่าสำหรับฉันเพราะมันมี "cruft" น้อยกว่าในช่วงกลางของประโยค มันง่ายกว่าที่ฉันจะเหลือบตาไปจนสุดสายตาจากนั้นมันก็เพื่อให้สมองของฉันแยกวิเคราะห์คำพูดพิเศษช่องว่างและข้อดี แน่นอนตอนนี้ผมชอบมากหลามสตริงรูปแบบที่ f"your {object} is in the {location}"3.6:
ดัสตินไวแอตต์

8
ฉันยังพบว่ามันยากที่จะอ่านและเขียนเมื่อตัวแปรต้องล้อมรอบด้วยเครื่องหมายคำพูด "your '" + object + "' is in the '" + location + "'"... ฉันไม่แน่ใจด้วยซ้ำว่าฉันจะได้รับในตอนนี้ ...
ดัสตินไวแอตต์

12

ตัวอย่างการชี้แจงอาร์กิวเมนต์ความสามารถในการอ่าน:

print 'id: ' + id + '; function: ' + function + '; method: ' + method + '; class: ' + class + ' -- total == ' + total

print 'id: %s; function: %s; method: %s; class: %s --total == %s' % \
   (id, function, method, class, total)

(โปรดทราบว่าตัวอย่างที่สองไม่เพียง แต่สามารถอ่านได้ง่ายขึ้น แต่ยังง่ายต่อการแก้ไขคุณสามารถเปลี่ยนเทมเพลตในหนึ่งบรรทัดและรายการตัวแปรในอีกอัน)

ปัญหาที่แยกต่างหากคือรหัส% s ยังแปลงเป็นสตริงมิฉะนั้นคุณต้องใช้การโทร str () ซึ่งอ่านได้น้อยกว่ารหัส% s ด้วย


1
ฉันไม่เห็นด้วยกับคำสั่งแรกของคุณ แต่เราสามารถยอมรับความแตกต่างฉันเพิ่งจะโพสต์คำตอบตามบรรทัดที่สองของคุณดังนั้นการ
โหวต

6

การใช้+ควรจะไม่หลีกเลี่ยงได้โดยทั่วไป ในหลายกรณีเป็นวิธีที่ถูกต้อง การใช้%sหรือ.join()เป็นที่นิยมเฉพาะในบางกรณีและมักจะเห็นได้ชัดเมื่อพวกเขาเป็นทางออกที่ดีกว่า

ในตัวอย่างของคุณคุณกำลังต่อกันสามสายเข้าด้วยกันและตัวอย่างการใช้+นั้นชัดเจนที่สุดและอ่านง่ายที่สุดดังนั้นจึงแนะนำ

%sหรือ.format()มีประโยชน์หากคุณต้องการสอดแทรกสตริงหรือค่าที่อยู่ตรงกลางของสตริงที่มีขนาดใหญ่กว่า ตัวอย่าง:

print "Hello %s, welcome to the computer!" % name

ในกรณีนี้การใช้%sมันสามารถอ่านได้มากขึ้นเนื่องจากคุณหลีกเลี่ยงการตัดสตริงแรกออกเป็นหลายส่วน โดยเฉพาะถ้าคุณกำลังแก้ไขหลายค่า

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


2

เนื่องจากลำดับของคำอาจเปลี่ยนแปลงในภาษาต่าง ๆ รูปแบบที่มี%sความจำเป็นถ้าคุณต้องการสนับสนุนการแปลสตริงในซอฟต์แวร์ของคุณอย่างถูกต้อง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.