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


214

我非常喜欢使用字典来格式化字符串。它可以帮助我阅读所使用的字符串格式,也可以利用现有的字典。例如:

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

但是我无法弄清楚python 3.x语法是否可以这样做(或者甚至可以)。我想做以下

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

Answers:


15

由于问题是特定于Python 3的,因此这里使用的从Python 3.6开始可用的新f字符串语法

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

注意外部单引号和内部双引号(您也可以采用其他方法)。


我会说f字符串的使用与python3方法更加一致。
Jonatas CD

2
请记住,f字符串是Python 3.6中的新功能,而不是3.5中的功能。
雨果

408

这对你有好处吗?

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

2
尝试了一下,它起作用了。但是我不理解“指针符号”的使用。我知道Python不使用指针,这是kwargs的示例吗?
Homunculus Reticulli

2
@HomunculusReticulli这是一个格式参数(最小字段宽度),而不是指向C ++样式的指针。docs.python.org/release/2.4.4/lib/typesseq-strings.html
D.Rosado 2012年

29
引入了Python 3.2 format_map与相似str.format(**mapping),除了mapping直接使用而不复制到dict。例如,这mapping是一个dict子类时,这很有用
diapir 2015年

1
@eugene **对python字典有什么作用?我认为它不会创建对象,因为print(** geopoint)无法给出语法错误
Nityesh Agarwal

4
@NityeshAgarwal传播带有name = value对作为单独参数的字典,即print(**geopoint)与相同print(longitude=71.091, latitude=41.123)。在许多语言中,它称为splat运算符。在JavaScript中,它称为传播算子。在python中,没有为该运算符指定特定名称。
abhisekp

79

要将字典解压缩为关键字参数,请使用**。此外,新型格式支持引用对象的属性和映射项:

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

2
我发现这个答案更好,因为为占位符添加位置索引会使代码更明确,更易于使用。特别是如果一个人有这样的事情:'{0[latitude]} {1[latitude]} {0[longitude]} {1[longitude]}'.format(geopoint0, geopoint1)
Løiten

1
如果您使用a defaultdict且没有所有键,这将非常有用
Whymarrh

65

由于Python 3.0和3.1已停产,而且没有人使用它们,因此您可以并且应该使用str.format_map(mapping)(Python 3.2+):

与相似str.format(**mapping)除了直接使用映射而不将其复制到dict。例如,如果映射是dict子类,则这很有用。

这意味着您可以使用例如defaultdict为丢失的键设置(并返回)默认值的a:

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

即使提供的映射是dict,而不是子类,也可能会稍快一些。

鉴于给定,差异并不大

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

然后

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

约比10 ns(2%)快

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

在我的Python 3.4.3上。当字典中有更多键时,差异可能会更大,并且


注意,格式语言比它灵活得多。它们可以包含索引表达式,属性访问等,因此您可以格式化整个对象或其中两个:

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

从3.6开始,您也可以使用插值字符串:

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

您只需要记住在嵌套引号中使用其他引号字符。这种方法的另一个好处是,它比调用格式化方法要快得多


不错,在性能方面有什么改进format吗?(鉴于它没有被复制到字典中)
巴尔加夫·饶

2
@BhargavRao没有太多,2%:D
Antti Haapala

@BhargavRao如果您正在寻找性能,请使用此'%(latitude)s %(longitude)s'%geopoint;)
Tcll

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

6

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

加上它的表现也明显优于f"""".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
您错过了一个;)print('%(latitude)s %(longitude)s'%geopoint)这也比另一个2快得多
Tcll

@tcll实际上我想要示例,可以在字符串中使用字典名称。像这样'%(geopoint["latitude"])s %(geopoint["longitude"])s'%{"geopoint":geopoint}
谢赫·阿卜杜勒·瓦希德

1

大多数答案仅格式化dict的值。

如果还要将密钥格式化为字符串,则可以使用dict.items()

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

输出:

(“纬度”,41.123)(“经度”,71.091)

如果要以套利方式格式化,即不显示元组之类的键值:

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

输出:

纬度为41.123,经度为71.091


请注意,“纬度”可能早于“经度” geopoint.items();)
Tcll
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.