【问题标题】:How do I format a string using a dictionary in python-3.x?如何在 python-3.x 中使用字典格式化字符串?
【发布时间】:2011-08-22 13:56:02
【问题描述】:

我非常喜欢使用字典来格式化字符串。它帮助我阅读我正在使用的字符串格式,并让我利用现有的字典。例如:

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)

【问题讨论】:

    标签: python string dictionary python-3.x


    【解决方案1】:
    print("{latitude} {longitude}".format(**geopoint))
    

    【讨论】:

    • 谢谢!我不知道为什么这没有更多的选票。
    • 这是最简单的选项,TBH。这也是将列表转换为可变参数的类似方式。应该是这样的。
    【解决方案2】:

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

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

    【讨论】:

    • 我发现这个答案更好,因为为占位符添加位置索引使代码更明确,更易于使用。特别是如果有这样的事情:'{0[latitude]} {1[latitude]} {0[longitude]} {1[longitude]}'.format(geopoint0, geopoint1)
    • 如果您使用 defaultdict 并且没有所有密钥,这很有用
    【解决方案3】:

    这对你有好处吗?

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

    【讨论】:

    • 试过了,效果很好。但我不明白“指针符号”的使用。我知道 Python 不使用指针,这是 kwargs 的一个例子吗?
    • @HomunculusReticulli 那是一个格式参数(最小字段宽度),而不是指向 C++ 风格指针的指针。 docs.python.org/release/2.4.4/lib/typesseq-strings.html
    • Python 3.2 引入了format_map类似于str.format(**mapping),只是mapping 是直接使用的,而不是复制到dict。这在例如 mapping 是 dict 子类时很有用
    • @eugene ** 对 python 字典有什么作用?我不认为它会创建一个对象,因为 print(**geopoint) 无法给出语法错误
    • @NityeshAgarwal 它使用名称=值对作为单个参数传播字典,即print(**geopoint)print(longitude=71.091, latitude=41.123) 相同。在许多语言中,它被称为 splat 运算符。在 JavaScript 中,它被称为 扩展运算符。在 python 中,这个操作符没有特别的名字。
    【解决方案4】:

    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() ;)
    【解决方案5】:

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

    类似于str.format(**mapping)只是直接使用映射而不是复制到dict。如果映射是dict 子类,这很有用。

    这意味着您可以使用例如 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'
    

    即使提供的映射是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 上。随着字典中的键越多,差异可能会更大,并且


    请注意,格式语言比这灵活得多;它们可以包含索引表达式、属性访问等,因此您可以格式化整个对象,或者其中 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'
    

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

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

    您只需要记住在嵌套引号中使用 other 引号字符。这种方法的另一个好处是它比calling a formatting method.快得多

    【讨论】:

    • 很好,与format 相比,有什么性能改进吗? (假设它没有被复制到字典中)
    • @BhargavRao 不多,2 % :D
    • @BhargavRao 如果您正在寻找性能,请使用此'%(latitude)s %(longitude)s'%geopoint ;)
    【解决方案6】:

    由于这个问题是针对 Python 3 的,所以这里使用 the new f-string syntax,自 Python 3.6 起可用:

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

    注意外面的单引号和里面的双引号(你也可以反过来做)。

    【讨论】:

    • 我会说 f-string 的使用更符合 python3 方法。
    • 请记住,f-strings 是 Python 3.6 的新内容,而不是 3.5。
    【解决方案7】:

    大多数答案只格式化了字典的值。

    如果您想也将密钥格式化为字符串,您可以使用 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() 的“纬度”有可能出现在“纬度”之前;)
    【解决方案8】:
    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
    

    【讨论】:

    • 你错过了一个 ;) print('%(latitude)s %(longitude)s'%geopoint) 这也比其他两个快得多
    • @tcll 实际上我想要示例,我可以在字符串中使用字典名称。像这样'%(geopoint["latitude"])s %(geopoint["longitude"])s'%{"geopoint":geopoint}
    【解决方案9】:

    使用 format_map 做你想做的事

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

    这样做的好处是

    • 字典不必被分解成参数(与**geopoint 相比)并且
    • 格式字符串只能访问提供的映射,而不是整个变量范围(与 F 字符串相比)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-06
      • 1970-01-01
      • 2023-03-23
      相关资源
      最近更新 更多