Làm cách nào để định dạng chuỗi bằng từ điển trong python-3.x?


215

Tôi là một fan hâm mộ lớn của việc sử dụng từ điển để định dạng chuỗi. Nó giúp tôi đọc định dạng chuỗi tôi đang sử dụng cũng như để tôi tận dụng các từ điển hiện có. Ví dụ:

class MyClass:
    def __init__(self):
        self.title = 'Title'

a = MyClass()
print 'The title is %(title)s' % a.__dict__

path = '/path/to/a/file'
print 'You put your file here: %(path)s' % locals()

Tuy nhiên tôi không thể tìm ra cú pháp python 3.x để làm tương tự (hoặc nếu điều đó thậm chí có thể). Tôi muốn làm như sau

# Fails, KeyError 'latitude'
geopoint = {'latitude':41.123,'longitude':71.091}
print '{latitude} {longitude}'.format(geopoint)

# Succeeds
print '{latitude} {longitude}'.format(latitude=41.123,longitude=71.091)

Câu trả lời:


15

Vì câu hỏi dành riêng cho Python 3, nên đây là sử dụng cú pháp chuỗi f mới , có sẵn từ Python 3.6:

>>> geopoint = {'latitude':41.123,'longitude':71.091}
>>> print(f'{geopoint["latitude"]} {geopoint["longitude"]}')
41.123 71.091

Lưu ý các dấu ngoặc đơn bên ngoài và dấu ngoặc kép bên trong (bạn cũng có thể làm theo cách khác).


Tôi muốn nói rằng việc sử dụng chuỗi f phù hợp hơn với cách tiếp cận python3.
CD Jonatas

2
Hãy nhớ rằng chuỗi f là mới đối với Python 3.6, và không phải trong 3.5.
Hugo

409

Điều này có tốt cho bạn không?

geopoint = {'latitude':41.123,'longitude':71.091}
print('{latitude} {longitude}'.format(**geopoint))

2
Đã thử điều này và nó đã làm việc. Nhưng tôi không hiểu việc sử dụng 'ký hiệu con trỏ'. Tôi biết Python không sử dụng con trỏ, đây có phải là ví dụ về kwargs không?
Homunculus Reticulli

2
@HomunculusReticulli Đó là tham số định dạng (Độ rộng trường tối thiểu), không phải là con trỏ tới kiểu con trỏ C ++. docs.python.org/release/2.4.4/lib/typesseq-strings.html
D.Rosado

29
Python 3.2 được giới thiệu format_map. Tương tự str.format(**mapping), ngoại trừ mappingđược sử dụng trực tiếp và không được sao chép vào a dict. Điều này hữu ích nếu ví dụ mappinglà một lớp con dict
diapir

1
@eugene ** làm gì với một từ điển python? Tôi không nghĩ rằng nó tạo ra một đối tượng vì in (** geopoint) không đưa ra lỗi cú pháp
Nityesh Agarwal

4
@NityeshAgarwal nó lan truyền từ điển với các cặp name = value dưới dạng các đối số riêng lẻ, nghĩa print(**geopoint)là giống như print(longitude=71.091, latitude=41.123). Trong nhiều ngôn ngữ, nó được gọi là toán tử splat . Trong JavaScript, nó được gọi là toán tử trải rộng . Trong python, không có tên cụ thể được đặt cho toán tử này.
abhisekp

79

Để giải nén một từ điển vào các đối số từ khóa, sử dụng **. Ngoài ra ,, định dạng kiểu mới hỗ trợ tham chiếu đến các thuộc tính của các đối tượng và các mục của ánh xạ:

'{0[latitude]} {0[longitude]}'.format(geopoint)
'The title is {0.title}s'.format(a) # the a from your first example

2
Tôi thấy câu trả lời này tốt hơn, vì việc thêm chỉ mục vị trí cho trình giữ chỗ làm cho mã rõ ràng hơn và dễ sử dụng hơn. Đặc biệt nếu một người có một cái gì đó như thế này:'{0[latitude]} {1[latitude]} {0[longitude]} {1[longitude]}'.format(geopoint0, geopoint1)
Løiten

1
Điều này hữu ích nếu bạn đang sử dụng defaultdictvà không có tất cả các khóa
Whymarrh

65

Vì Python 3.0 và 3.1 là EOL'ed và không ai sử dụng chúng, bạn có thể và nên sử dụng str.format_map(mapping)(Python 3.2+):

Tương tự str.format(**mapping), ngoại trừ việc ánh xạ được sử dụng trực tiếp và không được sao chép vào adict . Điều này rất hữu ích nếu ví dụ ánh xạ là một dictlớp con.

Điều này có nghĩa là bạn có thể sử dụng ví dụ a defaultdictsẽ đặt (và trả về) một giá trị mặc định cho các khóa bị thiếu:

>>> from collections import defaultdict
>>> vals = defaultdict(lambda: '<unset>', {'bar': 'baz'})
>>> 'foo is {foo} and bar is {bar}'.format_map(vals)
'foo is <unset> and bar is baz'

Ngay cả khi ánh xạ được cung cấp là một dict, không phải là một lớp con, điều này có thể vẫn sẽ nhanh hơn một chút.

Sự khác biệt không lớn mặc dù, được đưa ra

>>> d = dict(foo='x', bar='y', baz='z')

sau đó

>>> 'foo is {foo}, bar is {bar} and baz is {baz}'.format_map(d)

nhanh hơn khoảng 10 ns (2%)

>>> 'foo is {foo}, bar is {bar} and baz is {baz}'.format(**d)

trên Python của tôi 3.4.3. Sự khác biệt có lẽ sẽ lớn hơn khi có nhiều khóa hơn trong từ điển và


Lưu ý rằng ngôn ngữ định dạng linh hoạt hơn nhiều so với mặc dù; chúng có thể chứa các biểu thức được lập chỉ mục, truy cập thuộc tính, v.v. có thể định dạng toàn bộ một đối tượng hoặc 2 trong số chúng:

>>> p1 = {'latitude':41.123,'longitude':71.091}
>>> p2 = {'latitude':56.456,'longitude':23.456}
>>> '{0[latitude]} {0[longitude]} - {1[latitude]} {1[longitude]}'.format(p1, p2)
'41.123 71.091 - 56.456 23.456'

Bắt đầu từ 3.6, bạn cũng có thể sử dụng các chuỗi nội suy:

>>> f'lat:{p1["latitude"]} lng:{p1["longitude"]}'
'lat:41.123 lng:71.091'

Bạn chỉ cần nhớ sử dụng các ký tự trích dẫn khác trong các trích dẫn lồng nhau. Một nhược điểm khác của phương pháp này là nó nhanh hơn nhiều so với việc gọi một phương thức định dạng.


Đẹp một, có cải thiện hiệu suất hơn format? (Cho rằng nó không được sao chép vào một lệnh)
Bhargav Rao

2
@BhargavRao không nhiều, 2%: D
Antti Haapala

@BhargavRao nếu bạn đang tìm kiếm hiệu suất, hãy sử dụng cái này '%(latitude)s %(longitude)s'%geopoint;)
Tcll


6

Cú pháp Python 2 cũng hoạt động trong Python 3:

>>> class MyClass:
...     def __init__(self):
...         self.title = 'Title'
... 
>>> a = MyClass()
>>> print('The title is %(title)s' % a.__dict__)
The title is Title
>>> 
>>> path = '/path/to/a/file'
>>> print('You put your file here: %(path)s' % locals())
You put your file here: /path/to/a/file

cộng với đó cũng là hiệu suất đáng chú ý hơn f""hoặc "".format();)
Tcll

2
geopoint = {'latitude':41.123,'longitude':71.091}

# working examples.
print(f'{geopoint["latitude"]} {geopoint["longitude"]}') # from above answer
print('{geopoint[latitude]} {geopoint[longitude]}'.format(geopoint=geopoint)) # alternate for format method  (including dict name in string).
print('%(latitude)s %(longitude)s'%geopoint) # thanks @tcll

1
bạn đã bỏ lỡ một cái;) print('%(latitude)s %(longitude)s'%geopoint)cái này cũng nhanh hơn đáng kể so với cái kia 2
Tcll

@tcll Thật ra tôi muốn các ví dụ, nơi tôi có thể sử dụng tên từ điển bên trong chuỗi. Một cái gì đó như thế này'%(geopoint["latitude"])s %(geopoint["longitude"])s'%{"geopoint":geopoint}
Sheikh Abdul Wahid

1

Hầu hết các câu trả lời chỉ định dạng các giá trị của dict.

Nếu bạn cũng muốn định dạng khóa thành chuỗi, bạn có thể sử dụng dict.items () :

geopoint = {'latitude':41.123,'longitude':71.091}
print("{} {}".format(*geopoint.items()))

Đầu ra:

('vĩ độ', 41.123) ('kinh độ', 71.091)

Nếu bạn muốn định dạng theo cách tùy ý, nghĩa là không hiển thị các giá trị khóa như bộ dữ liệu:

from functools import reduce
print("{} is {} and {} is {}".format(*reduce((lambda x, y: x + y), [list(item) for item in geopoint.items()])))

Đầu ra:

vĩ độ là 41.123 và kinh độ là 71.091


lưu ý rằng có một cơ hội 'kinh độ' có thể đến trước 'vĩ độ' từ geopoint.items();)
Tcll
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.