มี Python ที่เทียบเท่ากับการแก้ไขสตริงของ Ruby หรือไม่?


343

ตัวอย่างทับทิม:

name = "Spongebob Squarepants"
puts "Who lives in a Pineapple under the sea? \n#{name}."

การต่อสตริง Python ที่ประสบความสำเร็จนั้นดูเหมือนฉัน


2
ปัญหาในที่นี้nameคือตัวแปรท้องถิ่นที่อยู่ในสตริงและใน Python คุณต้องส่งพจนานุกรมของตัวแปรโลคัลไปยัง formatter สตริงอย่างชัดเจนหากคุณต้องการใช้มัน
Katriel

นี่ไม่ใช่ปัญหาดั้งเดิม แต่ขอบคุณ ความคิดเห็นของคุณทำให้ฉันเข้าใจขอบเขตของตัวแปรได้ดีขึ้นเล็กน้อย :)
วรรณะ

1
คุณคิดยังไงกับเรื่องนี้ stackoverflow.com/questions/16504732/…
SalchiPapa


2
ดูstackoverflow.com/a/33264516/55721สำหรับคุณสมบัติที่แน่นอนนี้ใน 3.6
dss539

คำตอบ:


413

Python 3.6 จะเพิ่มการแก้ไขสตริงตัวอักษรที่คล้ายกับการแก้ไขสตริงของ Ruby เริ่มต้นด้วย Python เวอร์ชันนั้น (ซึ่งมีกำหนดจะวางจำหน่ายภายในสิ้นปี 2016) คุณจะสามารถรวมนิพจน์ใน "f-strings" เช่น

name = "Spongebob Squarepants"
print(f"Who lives in a Pineapple under the sea? {name}.")

ก่อนหน้า 3.6 สิ่งที่ใกล้เคียงที่สุดที่คุณสามารถทำได้คือ

name = "Spongebob Squarepants"
print("Who lives in a Pineapple under the sea? %(name)s." % locals())

%ผู้ประกอบการสามารถใช้สำหรับสตริงการแก้ไขในหลาม ตัวถูกดำเนินการแรกคือสตริงที่จะถูกสอดแทรกที่สองสามารถมีชนิดที่แตกต่างกันรวมถึง "การแมป" ชื่อฟิลด์การแมปกับค่าที่จะถูกสอดแทรก ที่นี่ฉันใช้พจนานุกรมของตัวแปรโลคัลlocals()เพื่อแม็พชื่อฟิลด์nameกับค่าเป็นตัวแปรโลคัล

รหัสเดียวกันโดยใช้.format()วิธีการของ Python เวอร์ชันล่าสุดจะมีลักษณะเช่นนี้:

name = "Spongebob Squarepants"
print("Who lives in a Pineapple under the sea? {name!s}.".format(**locals()))

นอกจากนี้ยังมีstring.Templateชั้นเรียน:

tmpl = string.Template("Who lives in a Pineapple under the sea? $name.")
print(tmpl.substitute(name="Spongebob Squarepants"))

@Caste ดูที่นี่: docs.python.org/library/stdtypes.html#string-formattingและโพสต์ความคิดเห็นติดตามหากคุณต้องการรายละเอียดเพิ่มเติม
mikej

ฉันเข้าใจส่วนสำคัญพื้นฐานของมันฉันไม่เข้าใจสัญลักษณ์และข้อความเพิ่มเติมทั้งหมดที่พบในตัวอย่างในเอกสารประกอบอย่างไรก็ตาม ทำไมการใช้งานการแปลงเป็นสตริงที่นี่:% (ภาษา) s 3 ใน '03d' มีความหมายว่าอะไร? ทำไมหลังจากสตริงถึงมี% \ การกำหนดตัวแปร (หากเป็นตัวแปรจริง) หลังจากนิพจน์การพิมพ์ทำให้ฉันสับสนเช่นกัน ขออภัยถ้านี่เป็นความเจ็บปวด!
วรรณะ

1
รูปแบบพื้นฐานสองรูปแบบที่ใช้ในตัวอย่างนี้ใช้%sสำหรับสตริงและ%03dสำหรับตัวเลขที่มีจำนวน 3 หลักด้วยศูนย์นำหน้า มันสามารถเขียนprint "%s has %03d" % ("Python", 2)ได้ ตัวอย่างจากนั้นใช้ประโยชน์จากการวางคีย์การทำแผนที่ในวงเล็บหลังจาก%ที่เป็นวิธีการให้ชื่อตัวแทนที่มีความหมายมากกว่าที่จะขึ้นอยู่กับการสั่งซื้อของพวกเขาในสตริง จากนั้นคุณส่งพจนานุกรมที่จับคู่ชื่อคีย์กับค่าของพจนานุกรม นั่นเป็นสาเหตุที่ Sven ใช้locals()ฟังก์ชันที่คืนค่าพจน์ที่มีตัวแปรโลคัลทั้งหมดของคุณดังนั้นมันจะแม็พnameกับค่าของชื่อ
mikej

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

@ วรรณะ: ใช่มันถูกต้องแล้ว โปรดทราบว่าคุณสามารถใช้ a sเป็นประเภทการแปลงได้เสมอPython สามารถแปลงอะไรก็ได้เป็นสตริง แต่แน่นอนว่าคุณจะสูญเสียความสามารถในการจัดรูปแบบพิเศษของประเภทการแปลงอื่น ๆ
Sven Marnach

143

ตั้งแต่ Python 2.6.X คุณอาจต้องการใช้:

"my {0} string: {1}".format("cool", "Hello there!")

27
โปรดสังเกตว่าตัว%ดำเนินการสำหรับการแก้ไขสตริงไม่ได้ถูกคัดค้านใน Python 3.x docs.python.org/dev/py3k/whatsnew/…ประกาศแผนการเลิกใช้%เริ่มต้นใน 3.1 แต่สิ่งนี้ไม่เคยเกิดขึ้น
Sven Marnach

8
% -syntax ยังมีชีวิตอยู่ใน Python 3 (ไม่ได้รับการคัดค้าน ณ Python 3.2)
Corey Goldberg

9
เพียงแค่ทราบ: หมายเลขใน{}ฉันสามารถตัดออก
วาด

32

ฉันได้พัฒนาinterpyแพคเกจที่จะช่วยให้การแก้ไขสตริงในหลาม

pip install interpyเพียงแค่ติดตั้งผ่านทาง จากนั้นเพิ่มบรรทัด# coding: interpyที่จุดเริ่มต้นของไฟล์ของคุณ!

ตัวอย่าง:

#!/usr/bin/env python
# coding: interpy

name = "Spongebob Squarepants"
print "Who lives in a Pineapple under the sea? \n#{name}."

3
ดูเหมือนจะไม่ปลอดภัยจริงๆ
d33tah

@ d33tah: ไม่ตราบใดที่สตริงเป็นที่รู้จักในเวลารวบรวม
Clément

28

การแก้ไขสตริงของ Python คล้ายกับ printf () ของ C

ถ้าคุณลอง:

name = "SpongeBob Squarepants"
print "Who lives in a Pineapple under the sea? %s" % name

แท็ก%sจะถูกแทนที่ด้วยnameตัวแปร คุณควรดูที่แท็กฟังก์ชั่นการพิมพ์: http://docs.python.org/library/functions.html


1
ฉันจะทำแบบนี้กับตัวแปร 2 ตัวได้อย่างไร
Julio Marins

16
@JulioMarins ใช้ tuple print "First is %s, second is %s" % (var1, var2)นี้:
kirbyfan64sos

28

สตริงการแก้ไขเป็นไปได้รวมกับงูหลาม 3.6 ตามที่ระบุใน PEP 498 คุณจะสามารถทำสิ่งนี้:

name = 'Spongebob Squarepants'
print(f'Who lives in a Pineapple under the sea? \n{name}')

โปรดทราบว่าฉันเกลียด Spongebob ดังนั้นการเขียนแบบนี้จึงเจ็บปวดเล็กน้อย :)


ขอบคุณสำหรับการอ้างอิง Spongebob (/ distaste): gonna upvote this now
javadba

4

คุณสามารถมีสิ่งนี้ได้

name = "Spongebob Squarepants"
print "Who lives in a Pineapple under the sea? \n{name}.".format(name=name)

http://docs.python.org/2/library/string.html#formatstrings


ฉันไม่เชื่อว่า OP ต้องการ#พิมพ์ พวกเขาเพียงแค่ใช้ไวยากรณ์ทับทิม
jaynp

คุณถูก. ฉันแก้ไขคำตอบ ฉันไม่คุ้นเคยกับ Ruby ดังนั้นฉันจึงคิดว่า#ตัวละครจะถูกพิมพ์
Quan ถึง

3
import inspect
def s(template, **kwargs):
    "Usage: s(string, **locals())"
    if not kwargs:
        frame = inspect.currentframe()
        try:
            kwargs = frame.f_back.f_locals
        finally:
            del frame
        if not kwargs:
            kwargs = globals()
    return template.format(**kwargs)

การใช้งาน:

a = 123
s('{a}', locals()) # print '123'
s('{a}') # it is equal to the above statement: print '123'
s('{b}') # raise an KeyError: b variable not found

PS: ประสิทธิภาพอาจเป็นปัญหา สิ่งนี้มีประโยชน์สำหรับสคริปต์โลคัลไม่ใช่สำหรับบันทึกการใช้งานจริง

duplicated:


2

สำหรับงูใหญ่ตัวเก่า (ทดสอบที่ 2.4) คำตอบอันดับต้นจะชี้ทาง คุณสามารถทำได้:

import string

def try_interp():
    d = 1
    f = 1.1
    s = "s"
    print string.Template("d: $d f: $f s: $s").substitute(**locals())

try_interp()

และคุณจะได้รับ

d: 1 f: 1.1 s: s

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