简体   繁体   English

如何在 python-3.x 中使用字典格式化字符串?

[英]How do I format a string using a dictionary in python-3.x?

I am a big fan of using dictionaries to format strings.我非常喜欢使用字典来格式化字符串。 It helps me read the string format I am using as well as let me take advantage of existing dictionaries.它帮助我阅读我正在使用的字符串格式,并让我利用现有的词典。 For example:例如:

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

However I cannot figure out the python 3.x syntax for doing the same (or if that is even possible).但是,我无法弄清楚执行相同操作的 python 3.x 语法(或者甚至可能)。 I would like to do the following我想做以下事情

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

Is this good for you?这对你有好处吗?

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

To unpack a dictionary into keyword arguments, use ** .要将字典解压缩为关键字参数,请使用** Also,, new-style formatting supports referring to attributes of objects and items of mappings:此外,新式格式支持引用对象的属性和映射项:

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

As Python 3.0 and 3.1 are EOL'ed and no one uses them, you can and should use str.format_map(mapping) (Python 3.2+):由于 Python 3.0 和 3.1 已停产并且没有人使用它们,因此您可以并且应该使用str.format_map(mapping) (Python 3.2+):

Similar to str.format(**mapping) , except that mapping is used directly and not copied to a dict .类似于str.format(**mapping)除了直接使用映射而不是复制到dict This is useful if for example mapping is a dict subclass.如果例如映射是dict子类,这很有用。

What this means is that you can use for example a defaultdict that would set (and return) a default value for keys that are missing:这意味着您可以使用例如defaultdict来设置(并返回)缺少的键的默认值:

>>> 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'

Even if the mapping provided is a dict , not a subclass, this would probably still be slightly faster.即使提供的映射是dict ,而不是子类,这可能仍然会稍微快一些。

The difference is not big though, given差异不大,但鉴于

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

then然后

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

is about 10 ns (2 %) faster than比 快 10 ns (2 %)

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

on my Python 3.4.3.在我的 Python 3.4.3 上。 The difference would probably be larger as more keys are in the dictionary, and随着字典中的键越多,差异可能会越大,并且


Note that the format language is much more flexible than that though;请注意,格式语言比这灵活得多; they can contain indexed expressions, attribute accesses and so on, so you can format a whole object, or 2 of them:它们可以包含索引表达式、属性访问等,因此您可以格式化整个对象,或其中的 2 个:

>>> 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'

Starting from 3.6 you can use the interpolated strings too:从 3.6 开始,您也可以使用内插字符串:

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

You just need to remember to use the other quote characters within the nested quotes.您只需要记住在嵌套引号中使用其他引号字符。 Another upside of this approach is that it is much faster than calling a formatting method.这种方法的另一个优点是它比调用格式化方法要快得多

print("{latitude} {longitude}".format(**geopoint))

Since the question is specific to Python 3, here's using the new f-string syntax , available since Python 3.6:由于该问题特定于 Python 3,因此这里使用自 Python 3.6 起可用的新 f-string 语法

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

Note the outer single quotes and inner double quotes (you could also do it the other way around).注意外部单引号和内部双引号(你也可以反过来做)。

The Python 2 syntax works in Python 3 as well: Python 2 语法也适用于 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
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

Most answers formatted only the values of the dict.大多数答案仅格式化了字典的值。

If you want to also format the key into the string you can use dict.items() :如果您还想将密钥格式化为字符串,您可以使用dict.items()

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

Output:输出:

('latitude', 41.123) ('longitude', 71.091) ('纬度', 41.123) ('经度', 71.091)

If you want to format in an arbitry way, that is, not showing the key-values like tuples:如果您想以任意方式格式化,即不显示像元组这样的键值:

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

Output:输出:

latitude is 41.123 and longitude is 71.091纬度为 41.123,经度为 71.091

Use format_map to do what you want使用 format_map 做你想做的事

print('{latitude} {longitude}'.format_map(geopoint))

This has the advantage that这样做的好处是

  • the dictionary does not have to be blown up into parameters (compared to **geopoint ) and that字典不必被分解成参数(与**geopoint相比)并且
  • the format string only has access to the provided map and not the entire scope of variables (compared to F-strings).格式字符串只能访问提供的映射,而不能访问整个变量范围(与 F 字符串相比)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM