Có một Python tương đương với phép nội suy chuỗi của Ruby không?


343

Ví dụ về Ruby:

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

Việc nối chuỗi Python thành công dường như dài dòng đối với tôi.


2
Vấn đề ở đây là namemột biến cục bộ nằm trong chuỗi và trong Python bạn phải chuyển từ điển của biến cục bộ sang bộ định dạng chuỗi nếu bạn muốn nó sử dụng chúng.
Katriel

Đây không phải là vấn đề ban đầu, nhưng cảm ơn. Nhận xét của bạn đã cho tôi hiểu rõ hơn một chút về phạm vi biến (điều mà tôi vẫn đang đạt được). :)
Caste

1
Bạn nghĩ gì về điều này, sau đó? stackoverflow.com/questions/16504732/
Mạnh


2
Xem stackoverflow.com/a/33264516/55721 để biết tính năng chính xác này trong 3.6
dss539

Câu trả lời:


413

Python 3.6 sẽ thêm phép nội suy chuỗi bằng chữ tương tự như phép nội suy chuỗi của Ruby. Bắt đầu với phiên bản Python đó (dự kiến ​​được phát hành vào cuối năm 2016), bạn sẽ có thể bao gồm các biểu thức trong "chuỗi f", ví dụ:

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

Trước 3.6, gần nhất bạn có thể nhận được điều này là

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

Các %nhà điều hành có thể được sử dụng cho chuỗi suy bằng Python. Toán hạng thứ nhất là chuỗi được nội suy, chuỗi thứ hai có thể có các loại khác nhau bao gồm "ánh xạ", ánh xạ tên trường tới các giá trị được nội suy. Ở đây tôi đã sử dụng từ điển của các biến cục bộ locals()để ánh xạ tên trường nametới giá trị của nó như một biến cục bộ.

Mã tương tự sử dụng .format()phương thức của các phiên bản Python gần đây sẽ trông như thế này:

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

Ngoài ra còn có string.Templatelớp:

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

@Caste thấy ở đây: docs.python.org/library/stdtypes.html#string-formatting và viết tiếp lên bình luận nếu bạn cần thêm bất kỳ chi tiết
mikej

Tôi hiểu ý chính cơ bản của nó, tuy nhiên tôi không hiểu đầy đủ tất cả các ký hiệu và văn bản bổ sung được tìm thấy trong ví dụ trong tài liệu. Tại sao việc sử dụng chuyển đổi thành chuỗi ở đây:% (ngôn ngữ) s 3 trong '03d' có nghĩa gì? Tại sao sau chuỗi có% \? Việc gán biến (nếu chúng là biến thực tế) sau biểu thức in cũng làm tôi bối rối. Xin lỗi nếu đây là một nỗi đau!
Caste

1
Hai định dạng cơ bản được sử dụng trong ví dụ là %scho một chuỗi và %03dcho một số được đệm thành 3 chữ số với các số 0 đứng đầu. Nó chỉ có thể được viết print "%s has %03d" % ("Python", 2). Ví dụ sau đó sử dụng việc đặt khóa ánh xạ trong ngoặc sau %đó là cách đặt tên giữ chỗ có ý nghĩa thay vì dựa vào thứ tự của chúng trong chuỗi. Sau đó, bạn chuyển một từ điển ánh xạ các tên chính đến giá trị của chúng. Đó là lý do tại sao Sven đang sử dụng locals()hàm trả về một dict chứa tất cả các biến cục bộ của bạn để nó sẽ ánh xạ nametới giá trị của tên
mikej

Việc sử dụng yêu cầu của một loại chuyển đổi là điều đầu tiên làm tôi bối rối. Vì vậy, sử dụng thuật ngữ tài liệu. % Bắt đầu chỉ định. Không có cờ chuyển đổi cho (ngôn ngữ), chỉ là loại chuyển đổi (dấu 's'); (số) tuy nhiên có một (hoặc hai) cờ chuyển đổi tương ứng là '0' (và '3'). 'D' là loại chuyển đổi và biểu thị nó là một số nguyên. Tôi đã hiểu đúng chưa?
Caste

@Caste: Vâng, về cơ bản là đúng. Lưu ý rằng bạn luôn có thể sử dụng slàm loại chuyển đổi - Python có thể chuyển đổi mọi thứ thành chuỗi. Nhưng tất nhiên bạn sẽ mất khả năng định dạng đặc biệt của các loại chuyển đổi khác.
Sven Marnach

143

Vì Python 2.6.X bạn có thể muốn sử dụng:

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

27
Lưu ý rằng %toán tử cho phép nội suy chuỗi không bị phản đối trong Python 3.x. docs.python.org/dev/py3k/whatsnew/ từ thông báo kế hoạch từ chối %bắt đầu từ 3.1, nhưng điều này không bao giờ xảy ra.
Sven Marnach

8
% -syntax vẫn tồn tại trong Python 3 (không bị phản đối kể từ Python 3.2)
Corey Goldberg

9
Chỉ cần một lưu ý: số trong {}tôi có thể loại bỏ.
vẽ

32

Tôi đã phát triển gói interpy , cho phép nội suy chuỗi trong Python .

Chỉ cần cài đặt nó qua pip install interpy. Và sau đó, thêm dòng # coding: interpyở đầu tập tin của bạn!

Thí dụ:

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

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

3
Điều này có vẻ thực sự không an toàn.
d33tah

@ d33tah: Không, miễn là các chuỗi được biết tại thời điểm biên dịch.
Clément

28

Nội suy chuỗi của Python tương tự như printf () của C

Nếu bạn cố gắng:

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

Thẻ %ssẽ được thay thế bằng namebiến. Bạn nên xem qua các thẻ chức năng in: http://docs.python.org/l Library / fiances.html


1
Làm thế nào tôi có thể làm theo cách này với 2 biến?
Julio Marins

16
@JulioMarins Sử dụng một tuple : print "First is %s, second is %s" % (var1, var2).
kirbyfan64sos


4

Bạn cũng có thể có cái này

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

http://docs.python.org/2/l Library / chuỗi.html # formatstrings


Tôi không tin OP dự định #sẽ được in. Họ chỉ đang sử dụng cú pháp Ruby.
jaynp

Bạn đúng. Tôi chỉnh sửa câu trả lời. Tôi không quen thuộc với Ruby, vì vậy tôi nghĩ rằng #nhân vật sẽ được in.
Quan Tới

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)

Sử dụng:

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: hiệu suất có thể là một vấn đề. Điều này hữu ích cho các tập lệnh cục bộ, không phải cho nhật ký sản xuất.

Sao y:


2

Đối với Python cũ (đã thử nghiệm trên 2.4), giải pháp hàng đầu chỉ đường. Bạn có thể làm được việc này:

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()

Và bạn nhận được

d: 1 f: 1.1 s: s

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.