2013-10-23 12 views
8

Tôi thường sử dụng mô hình sau (như đã đề cập trong this question):hình thức viết tắt của string.Format (..., người dân địa phương **())

a=1 
s= "{a}".format(**locals()) 

Tôi nghĩ rằng đó là một cách tuyệt vời để viết một cách dễ dàng có thể đọc được mã.

Đôi khi nó là hữu ích để "chuỗi" các định dạng chuỗi, để "modularize" việc tạo ra các chuỗi phức tạp:

a="1" 
b="2" 
c="{a}+{b}".format(**locals()) 
d="{c} is a sum".format(**locals()) 
#d=="1+2 is a sum" 

Khá sớm, các mã được quấy rầy với X.format(**locals()). Để giải quyết vấn đề này, tôi đã cố gắng để tạo ra một lambda:

f= lambda x: x.format(**locals()) 
a="1" 
b="2" 
c= f("{a}+{b}") 
d= f("{c} is a sum") 

nhưng điều này ném một KeyError, vì locals() là người dân địa phương của lambda.

Tôi cũng đã cố gắng để áp dụng định dạng duy nhất trên chuỗi cuối cùng:

a="1" 
b="2" 
c="{a}+{b}" 
d="{c} is a sum".format(**locals()) 
#d=="{a}+{b} is a sum" 

Nhưng điều này không làm việc, kể từ python chỉ định dạng một lần. Bây giờ, tôi có thể viết một hàm định dạng tục cho đến khi không có gì hơn để làm:

def my_format(string, vars): 
    f= string.format(**vars) 
    return f if f==string else my_format(f, vars) 

nhưng tôi đang tự hỏi: có cách nào tốt hơn để làm điều này?

Trả lời

4

f = lambda x, l=locals(): x.format(**l) xuất hiện để làm việc ...

và nếu bạn muốn có một phiên bản đó là (chậm hơn và có lẽ rất nhiều) hơn một chút bao gồm tất cả:

fg = lambda x, l=locals(), g=globals(): x.format(**dict(g.items() + l.items())) 

sẽ tìm thấy những biểu tượng trong cả hai người dân địa phương hoặc hình cầu.

+0

Bạn có thể muốn người dân địa phương ghi đè hình ảnh toàn cầu. Hiện tại, bạn có nó theo cách khác vòng, kể từ sau đối số để giành chiến thắng dict. – Collin

+0

điểm tốt ... tôi sẽ thực hiện thay đổi đó. –

0

Đó không phải là một lớp lót, nhưng nó hoạt động:

def fmt(s, l=locals()): 
    while '{' in s: 
     s = s.format(**l) 
    return s 

a="1" 
b="2" 
c="{a}+{b}" 
d="{c} is a sum" 

print fmt(d) # 1+2 is a sum 

Dưới đây là một dòng một (và hơi kém hiệu quả) phiên bản đệ quy:

fmt = lambda s, l=locals(): fmt(s.format(**l), l=l) if '{' in s else s 
2

Nếu bạn chỉ cần làm điều này trong vòng phạm vi chức năng dưới dạng phím tắt cục bộ, phần sau sẽ hoạt động:

def formatter(fmt, loc=locals()): 
    return fmt.format(**loc) 

Tuy nhiên, điều này sẽ ràng buộc giá trị urned by locals() tại thời điểm khai báo hàm, thay vì thực thi, vì vậy nó sẽ không được cập nhật khi các giá trị thay đổi, cũng không hữu ích khi được gọi từ bất kỳ phạm vi nào khác.

Nếu bạn muốn được tiếp cận với phương pháp gọi của locals, bạn cần phải inspect các cuộc gọi stack (http://docs.python.org/2/library/inspect.html)

import inspect 

def formatter(fmt): 
    parent = inspect.stack()[1][0] # 1 = the previous frame context 
            # 0 = the frame object 
    return fmt.format(**parent.f_locals) 

Lưu ý rằng điều này có thể không làm việc cho triển khai của python mà không phải là CPython.

Bây giờ bạn có thể làm:

a = "1" 
b = "2" 
c = formatter("{a}+{b}") 
d = formatter("{c} is a sum") 
+0

thực sự, điều này là đúng đôi khi, nhưng không phải luôn luôn ... có vẻ như người dân địa phương() thực sự trả về một con trỏ đến giá trị dict của 'người dân địa phương', mà dường như thay đổi. Bạn có thể thực hiện các thí nghiệm sau: 'f = locals(); x = 1; g = locals(); f == g', sẽ là True, mặc dù bạn đã sửa đổi một giá trị cục bộ giữa f và g. Ngoài ra: 'def fn (x, l = locals()): in l [x]; x = 2; fn ('x'); x = 3; fn ('x') 'sẽ in 2, sau đó 3. Có vẻ như nó đôi khi phải đúng, vì vậy đó là một nhận xét tốt, nhưng dường như có rất nhiều trường hợp thực tế mà bạn có thể bỏ qua nó. –

0

Bắt đầu với Python 3.6 ảnh hưởng của **locals() đã được bao gồm trong string#format hay đúng hơn là "định dạng xâu".

Xem thêm PEP 498Python 3.6 release notes.

Các vấn đề liên quan