Python หลายวิธีในการจัดรูปแบบสตริง - เวอร์ชันเก่า (กำลังจะ) เลิกใช้แล้วหรือไม่?


106

Python มีอย่างน้อยหกวิธีในการจัดรูปแบบสตริง:

In [1]: world = "Earth"

# method 1a
In [2]: "Hello, %s" % world
Out[2]: 'Hello, Earth'

# method 1b
In [3]: "Hello, %(planet)s" % {"planet": world}
Out[3]: 'Hello, Earth'

# method 2a
In [4]: "Hello, {0}".format(world)
Out[4]: 'Hello, Earth'

# method 2b
In [5]: "Hello, {planet}".format(planet=world)
Out[5]: 'Hello, Earth'

# method 2c
In [6]: f"Hello, {world}"
Out[6]: 'Hello, Earth'

In [7]: from string import Template

# method 3
In [8]: Template("Hello, $planet").substitute(planet=world)
Out[8]: 'Hello, Earth'

ประวัติโดยย่อของวิธีการต่างๆ:

  • printfการจัดรูปแบบสไตล์มีมาตั้งแต่วัยเด็ก Pythons
  • Templateระดับได้รับการแนะนำในหลาม 2.4
  • formatวิธีการได้รับการแนะนำในหลาม 2.6
  • f-strings ถูกนำมาใช้ใน Python 3.6

คำถามของฉันคือ:

  • การprintfจัดรูปแบบสไตล์เลิกใช้งานหรือจะเลิกใช้งาน
  • ในการTemplate classเป็นsubstituteวิธีการเลิกใช้หรือกำลังจะถูกเลิก? (ฉันไม่ได้พูดถึงsafe_substituteซึ่งตามที่ฉันเข้าใจมันมีความสามารถพิเศษ)

คำถามที่คล้ายกันและทำไมฉันคิดว่ามันไม่ซ้ำกัน:

ดูสิ่งนี้ด้วย


1
ฉันจำเป็นต้องชี้ว่าคุณลืมFormatterชั้นเรียนหรือไม่?
Martijn Pieters

คำตอบ:


14

แม้ว่าจะมีข้อบ่งชี้ต่าง ๆ ในเอกสารว่า.formatและ f-strings นั้นเหนือกว่า%สตริง แต่ก็ไม่มีแผนรอดที่จะเลิกใช้งานในภายหลัง

ในการกระทำปัญหา # 14123: กล่าวอย่างชัดเจนว่าการจัดรูปแบบสตริง% แบบเก่ามีข้อแม้ แต่จะไม่หายไปในเร็ว ๆ นี้ ซึ่งได้รับแรงบันดาลใจจากปัญหาระบุว่าไม่มีแผนปัจจุบันที่จะเลิกใช้งานการจัดรูปแบบสไตล์ printfเอกสารเกี่ยวกับการจัดรูปแบบ%ได้รับการแก้ไขเพื่อให้มีวลีนี้:

เนื่องจากไวยากรณ์การจัดรูปแบบสตริงใหม่มีความยืดหยุ่นมากขึ้นและจัดการกับ tuples และพจนานุกรมได้อย่างเป็นธรรมชาติจึงขอแนะนำให้ใช้โค้ดใหม่ แต่ไม่มีแผนปัจจุบันเพื่อจัดรูปแบบ printf สไตล์การเลิกใช้

(เน้นของฉัน)

วลีนี้ถูกลบออกในภายหลังในการกระทำClose # 4966: ปรับปรุงเอกสารลำดับเพื่ออธิบายสถานะของ Python สมัยใหม่ได้ดีขึ้น นี่อาจดูเหมือนเป็นสัญญาณว่าแผนการเลิกใช้%การจัดรูปแบบกลับมาอยู่ในการ์ด ... แต่การดำน้ำในตัวติดตามข้อบกพร่องเผยให้เห็นว่าเจตนานั้นตรงกันข้าม เกี่ยวกับการติดตามข้อผิดพลาดที่ผู้เขียนของการกระทำลักษณะการเปลี่ยนแปลงเช่นนี้ :

  • เปลี่ยนร้อยแก้วที่อธิบายความสัมพันธ์ระหว่างการจัดรูปแบบสไตล์ printf และวิธีการจัดรูปแบบ str. (โดยเจตนาลบความหมายที่ว่าอดีตเป็นอันตรายที่แท้จริงของการหายไป - เราไม่ควรพิจารณาอย่างจริงจังที่จะฆ่ามันทิ้ง)

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

ยิ่งไปกว่านั้นการเปลี่ยนแปลงล่าสุดในย่อหน้านั้นในเดือนมีนาคม 2017 เปลี่ยนจากนี้ ...

การดำเนินการจัดรูปแบบที่อธิบายไว้ที่นี่แสดงให้เห็นถึงความไม่ชอบมาพากลหลายประการที่นำไปสู่ข้อผิดพลาดทั่วไปหลายประการ (เช่นไม่สามารถแสดงสิ่งที่เพิ่มขึ้นและพจนานุกรมอย่างถูกต้อง) การใช้ตัวอักษรสตริงที่จัดรูปแบบใหม่กว่าหรือstr.formatอินเทอร์เฟซจะช่วยหลีกเลี่ยงข้อผิดพลาดเหล่านี้ ทางเลือกเหล่านี้ยังให้แนวทางในการจัดรูปแบบข้อความที่มีประสิทธิภาพยืดหยุ่นและขยายได้มากขึ้น

... สำหรับสิ่งนี้:

การดำเนินการจัดรูปแบบที่อธิบายไว้ที่นี่แสดงให้เห็นถึงความไม่ชอบมาพากลหลายประการที่นำไปสู่ข้อผิดพลาดทั่วไปหลายประการ (เช่นไม่สามารถแสดงสิ่งที่เพิ่มขึ้นและพจนานุกรมอย่างถูกต้อง) การใช้ตัวอักษรสตริงที่จัดรูปแบบใหม่กว่าstr.formatอินเทอร์เฟซหรือสตริงเทมเพลตอาจช่วยหลีกเลี่ยงข้อผิดพลาดเหล่านี้ ทางเลือกเหล่านี้แต่ละทางให้การแลกเปลี่ยนและประโยชน์ของความเรียบง่ายความยืดหยุ่นและ / หรือความสามารถในการขยายของตนเอง

สังเกตเห็นความเปลี่ยนแปลงจาก "จะช่วยหลีกเลี่ยง" เพื่อ "หลีกเลี่ยงการช่วยเหลือพฤษภาคม" และวิธีการที่ชัดเจนของข้อเสนอแนะ.formatและ F-สตริงได้ถูกแทนที่โดยปุยร้อยแก้วยังไม่มีข้อยุติเกี่ยวกับวิธีการของแต่ละสไตล์"ให้ไม่ชอบการค้าของตัวเองและผลประโยชน์" นั่นคือไม่เพียง แต่การเลิกใช้งานอย่างเป็นทางการไม่ได้อยู่ในการ์ดอีกต่อไป แต่เอกสารปัจจุบันยอมรับอย่างเปิดเผยว่า%อย่างน้อยการจัดรูปแบบก็มี "ประโยชน์" บางประการเหนือวิธีอื่น ๆ

ฉันอนุมานจากทั้งหมดนี้ว่าการเคลื่อนไหวเพื่อเลิกใช้หรือลบ%การจัดรูปแบบไม่เพียง แต่สะดุด แต่ยังพ่ายแพ้อย่างหมดจดและถาวร


2
การเปลี่ยนแปลงภาษาปุยถูกบันทึกอยู่ในปิดปากดูแล Mercurial (อื่น) ที่ไม่ได้ต้องการที่จะเห็น Mercurial ทิ้งไว้ข้างหลังกับ codebase %ขนาดใหญ่เกินไปที่จะกำจัดการใช้งานของ ตอนนี้นโยบาย 'ไม่มีตัวดัดแปลงโค้ดขนาดใหญ่' ถูกยกเลิกการคัดค้านของพวกเขาก็จางหายไปเช่นกัน ในระยะยาวการรักษาทั้งสองรูปแบบโดยไม่มีประโยชน์เหลืออยู่% ในบางจุดไวยากรณ์ของ printf จะถูกลบออกไป เราไม่รู้ว่าเมื่อไหร่และภาษาก็ควรจะกระชับลง
Martijn Pieters

@MartijnPieters น่าสนใจ ดูเหมือนว่าคุณจะมีความรู้มากมายเกี่ยวกับการตัดสินใจครั้งนี้ที่ฉันขาด สำหรับสิ่งที่คุ้มค่าฉันคิดว่าคำตอบที่อ้างอิงได้ดีจากคุณโดยสรุปประเด็นเหล่านี้ (ไม่ว่าจะเป็นคำตอบใหม่หรือการแก้ไขคำตอบที่มีอยู่ของคุณ) จะมีค่า
Mark Amery

58

.format()วิธีการใหม่นี้มีไว้เพื่อแทนที่%ไวยากรณ์การจัดรูปแบบเก่า หลังได้รับ de-เน้น ( แต่ไม่ยกเลิกอย่างเป็นทางการเลย ) เอกสารวิธีการระบุมาก:

วิธีการจัดรูปแบบสตริงนี้เป็นมาตรฐานใหม่ใน Python 3 และควรเป็นที่ต้องการสำหรับการ%จัดรูปแบบที่อธิบายไว้ในString Formatting Operationsในโค้ดใหม่

(เน้นของฉัน)

เพื่อรักษาความเข้ากันได้ย้อนหลังและจะทำให้การเปลี่ยนแปลงได้ง่ายขึ้นรูปแบบเก่าได้ถูกทิ้งในสถานที่สำหรับตอนนี้ จากข้อเสนอ PEP 3101เดิม:

ความเข้ากันได้ย้อนหลัง

สามารถรักษาความเข้ากันได้แบบย้อนกลับโดยปล่อยให้กลไกที่มีอยู่เดิม ระบบใหม่จะไม่ชนกับชื่อเมธอดใด ๆ ของเทคนิคการจัดรูปแบบสตริงที่มีอยู่ดังนั้นทั้งสองระบบสามารถอยู่ร่วมกันได้จนกว่าจะถึงเวลาเลิกใช้งานระบบเก่า

หมายเหตุจนกว่าจะถึงเวลาที่จะเลิกใช้ระบบเก่า ; มันยังไม่ได้รับการคัดค้าน แต่ระบบใหม่ที่จะใช้เมื่อใดก็ตามที่คุณเขียนโค้ดใหม่

ระบบใหม่มีข้อดีคือคุณสามารถรวมวิธีทูเพิลและพจนานุกรมของ%ฟอร์แมตเตอร์เก่า:

"{greeting}, {0}".format(world, greeting='Hello')

และสามารถขยายได้ผ่านobject.__format__()ตะขอที่ใช้จัดการการจัดรูปแบบของค่าแต่ละค่า

โปรดสังเกตว่าระบบเก่ามี%และTemplateคลาสโดยที่ระบบหลังอนุญาตให้คุณสร้างคลาสย่อยที่เพิ่มหรือปรับเปลี่ยนพฤติกรรมของมัน ระบบรูปแบบใหม่มีFormatterคลาสเพื่อเติมเต็มช่องเดียวกัน

งูหลาม 3 ได้ก้าวห่างไกลจากการเลิกใช้แทนคำเตือนให้คุณในprintfสไตล์สตริงการจัดรูปแบบส่วน :

หมายเหตุ : การดำเนินการจัดรูปแบบที่อธิบายไว้ที่นี่แสดงให้เห็นถึงความไม่ชอบมาพากลหลายประการที่นำไปสู่ข้อผิดพลาดทั่วไปหลายประการ (เช่นไม่สามารถแสดงสิ่งทอและพจนานุกรมได้อย่างถูกต้อง) การใช้ตัวอักษรสตริงที่จัดรูปแบบใหม่กว่าหรือstr.format()อินเทอร์เฟซจะช่วยหลีกเลี่ยงข้อผิดพลาดเหล่านี้ ทางเลือกเหล่านี้ยังให้แนวทางในการจัดรูปแบบข้อความที่มีประสิทธิภาพยืดหยุ่นและขยายได้มากขึ้น

Python 3.6 ยังเพิ่มตัวอักษรสตริงที่จัดรูปแบบซึ่งจะอยู่ในบรรทัดนิพจน์ลงในสตริงรูปแบบ นี่เป็นวิธีที่เร็วที่สุดในการสร้างสตริงที่มีค่า interpolated และควรใช้แทนstr.format()ทุกที่ที่คุณสามารถใช้ลิเทอรัลได้


4
และด้วยFormatterคุณสามารถสร้างรูปแบบที่กำหนดเองเช่นรูปแบบที่datetimeวัตถุใช้ นอกจากนี้เนื่องจาก.formatเป็นฟังก์ชันคุณสามารถใช้เพื่อสร้างการจัดรูปแบบขี้เกียจที่เรียกได้ได้โดยตรงมากขึ้นเช่นfmt = '{} - {}'.format; fmt(a, b)
Jon Clements

ฉันไม่เห็นว่าTemplateเกี่ยวข้องกับ%หรือกับระบบเก่าอย่างไร โดยเฉพาะอย่างยิ่ง PEP คุณเชื่อมโยงสถานะแม้ว่าข้อเสนอนี้จะมีความทับซ้อนกันstring.Templateแต่ก็รู้สึกว่าแต่ละข้อตอบสนองความต้องการที่แตกต่างกันและข้อเสนอนั้นไม่ได้ขัดขวางอีกฝ่าย ในคำตอบของคุณอาจสับสนว่าTemplateการจัดรูปแบบซึ่งเป็นส่วนหนึ่งของระบบเก่าก็เลิกใช้แล้วเช่นกัน
Bakuriu

@ บาคุริว: ใช่ฉันคิดว่าฉันพลาดส่วนนั้นไป แต่ในความคิดของฉันระดับสามารถเติมเต็มความต้องการเช่นเดียวกับFormatter string.Template()
Martijn Pieters

1
[...]should be preferred to the % formatting[...]ส่วนนี้ถูกลบออกจากเอกสาร docs.python.org/3/library/stdtypes.html#str.format
AXO

ฉันคิดว่าคำตอบนี้ทำให้เข้าใจผิดในขณะนี้ ข้อความแรกที่ยกมาได้ถูกลบออกจากเอกสาร Python 3 และดูเหมือนจะค่อนข้างชัดเจนสำหรับฉันว่าไม่มีความตั้งใจที่จะเลิกใช้งาน คำตอบนี้ยังคงมีคุณค่าทางประวัติศาสตร์ แต่ฉันมีแนวโน้มที่จะปรับแต่งข้อความเพื่อหลีกเลี่ยงข้อเสนอแนะใด ๆ ที่การเลิกใช้งานยังคงอยู่ในการ์ดและเพื่อแก้ไขครึ่งแรกของคำตอบส่วนใหญ่ให้เป็นอดีตกาล เมื่อถึงจุดหนึ่งฉันจะทำเองถ้าคุณไม่คัดค้าน แต่คิดว่าฉันจะแสดงความคิดเห็นก่อนเพื่อให้คุณมีโอกาสเปลี่ยนแปลงตัวเองหากคุณต้องการ
Mark Amery

45

ตัว%ดำเนินการสำหรับการจัดรูปแบบสตริงไม่ได้เลิกใช้งานและจะไม่ถูกลบออกแม้จะมีคำตอบอื่น ๆ ก็ตาม
ทุกครั้งที่มีการยกหัวข้อในรายการการพัฒนา Python จะมีการโต้เถียงกันอย่างชัดเจนว่าแบบไหนดีกว่ากัน แต่ไม่มีการโต้เถียงว่าจะเอาวิธีแบบคลาสสิกออกหรือไม่ - มันจะยังคงอยู่ แม้จะมีการระบุไว้ใน PEP 3101 แต่ Python 3.1 ก็มาแล้วและ%การจัดรูปแบบยังคงอยู่

ข้อความสำหรับการรักษาสไตล์คลาสสิกมีความชัดเจน: เรียบง่ายรวดเร็วรวดเร็วในการทำสิ่งสั้น ๆ การใช้.formatวิธีนี้ไม่สามารถอ่านได้มากขึ้นเสมอไปและแทบจะไม่มีใครเลยแม้แต่ในกลุ่มนักพัฒนาหลักก็สามารถใช้ไวยากรณ์แบบเต็มที่ให้มาโดย.formatไม่ต้องดูข้อมูลอ้างอิงแม้แต่ในปี 2009 ก็มีข้อความเช่นนี้: http: // mail python.org/pipermail/python-dev/2009-October/092529.html - เรื่องนี้แทบจะไม่ปรากฏในรายการเลย

ปรับปรุง 2016

ในรุ่นปัจจุบันการพัฒนาหลาม (ซึ่งจะกลายเป็นงูหลาม 3.6) มีวิธีที่สามของสตริงแก้ไขอธิบายในPEP-0498 มันกำหนดคำนำหน้าอ้างใหม่f""(นอกเหนือจากปัจจุบันu"", b""และr"")

นำหน้าสตริงโดยfจะเรียกใช้เมธอดบนอ็อบเจ็กต์สตริงที่รันไทม์ซึ่งจะแทรกตัวแปรจากขอบเขตปัจจุบันลงในสตริงโดยอัตโนมัติ:

>>> value = 80
>>> f'The value is {value}.'
'The value is 80.'

3
ดีกว่ามากที่จะอนุญาตให้ประเภทต่างๆนำไปใช้เอง__format__ได้ ยกตัวอย่างเช่นVSformat(Decimal('0.1'), '.20f') '%.20f' % Decimal('0.1')ตัวหลังบังคับทศนิยมให้ลอย
Eryk Sun

2
NB. ฉันไม่ได้เถียงว่ารูปแบบเก่าดีกว่าทุกประการเพียงแค่ว่ามันสั้นกว่าและบางครั้งก็อ่านง่ายขึ้น (และบางครั้งก็ไม่) แน่นอนว่าวิธีใหม่นี้ยืดหยุ่นกว่ามาก
jsbueno

มีค่าเทียบเท่าfใน Python 3 หรือไม่?
Daniel

f-stringsที่ใช้ข้างต้นเป็นคุณลักษณะใหม่ในภาษาที่เป็นของงูใหญ่ 3.6 ไม่มีอยู่ในเวอร์ชันก่อนหน้าและจะทำให้เกิดข้อผิดพลาดทางไวยากรณ์ขึ้น
jsbueno

20

ตำแหน่งล่าสุดของ Guido เกี่ยวกับเรื่องนี้ดูเหมือนจะระบุไว้ที่นี่:

มีอะไรใหม่ใน Python 3.0

PEP 3101: แนวทางใหม่ในการจัดรูปแบบสตริง

ระบบใหม่สำหรับการดำเนินการจัดรูปแบบสตริงในตัวจะแทนที่ตัวดำเนินการจัดรูปแบบสตริง% (อย่างไรก็ตามตัวดำเนินการ% ยังคงได้รับการสนับสนุนซึ่งจะเลิกใช้งานใน Python 3.1 และลบออกจากภาษาในภายหลัง) อ่าน PEP 3101 สำหรับสกู๊ปฉบับเต็ม

และPEP3101เองซึ่งมีการแก้ไขครั้งล่าสุดย้อนหลังไปเมื่อวันที่ (ศ. 30 ก.ย. 2554) ดังนั้นจึงไม่มีความคืบหน้าใด ๆ ในตอนนี้ฉันคิดว่า


18

เมื่อดูเอกสาร Python รุ่นเก่าและ PEP 3101 มีข้อความว่าตัวดำเนินการ% จะถูกเลิกใช้งานและลบออกจากภาษาในอนาคต คำสั่งต่อไปอยู่ในเอกสารงูหลามงูหลาม 3.0, 3.1 และ 3.2:

เนื่องจาก str.format () ค่อนข้างใหม่โค้ด Python จำนวนมากยังคงใช้ตัวดำเนินการ% อย่างไรก็ตามเนื่องจากรูปแบบเก่านี้จะถูกลบออกจากภาษาในที่สุดจึงควรใช้ str.format ()

หากคุณไปที่ส่วนเดียวกันในเอกสาร Python 3.3 และ 3.4 คุณจะเห็นคำสั่งนั้นถูกลบออก ฉันยังไม่พบคำสั่งอื่นใดในเอกสารที่ระบุว่าโอเปอเรเตอร์จะถูกเลิกใช้หรือลบออกจากภาษา สิ่งสำคัญที่ควรทราบคือPEP3101ไม่มีการแก้ไขมานานกว่าสองปีครึ่ง (ศ. 30 ก.ย. 2554)

อัปเดต

PEP461 ยอมรับการเพิ่ม% การจัดรูปแบบเป็นไบต์และ bytearray และควรเป็นส่วนหนึ่งของ Python 3.5 หรือ 3.6 เป็นสัญญาณอีกอย่างหนึ่งว่าตัวดำเนินการ% ยังมีชีวิตอยู่และกำลังเตะ

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