嵌套的f字符串

时间:2016-12-19 03:27:58

标签: python python-3.x string-formatting python-3.6 f-string

感谢David Beazley's tweet,我最近发现新的Python 3.6 f-strings也可以嵌套:

>>> x = 42
>>> f'''-{f"""*{f"+{f'.{x}.'}+"}*"""}-'''
'-*+.42.+*-'

或者:

days

虽然我很惊讶这是可能的,但我很遗憾实际上是什么时候,嵌套f字符串是否有用?这可以涵盖哪些用例?

注意:PEP本身没有提到嵌套f字符串,但有一个specific test case

10 个答案:

答案 0 :(得分:37)

我不认为格式化字符串文字允许嵌套(通过嵌套,我认为是f'{f".."}')是仔细考虑可能的用例的结果,我更确信它&# 39; s只是为了使它们符合规范而被允许。

规范声明他们在括号内support full Python expressions。它还声明格式化的字符串文字实际上只是在运行时评估的表达式(请参阅herehere)。因此,只有将格式化的字符串文字作为另一个格式化字符串文字中的表达式才有意义,禁止它会否定对Python表达式的完全支持。

您无法找到文档中提到的用例(并且只在测试套件中找到测试用例),这是因为这可能是实现的一个很好的(副作用)效果,而不是它。激励用例。

答案 1 :(得分:8)

我想这是为了在同一行传递格式参数,从而简化 f-strings 的使用。

例如:

>>> import decimal
>>> width = 10
>>> precision = 4
>>> value = decimal.Decimal("12.34567")
>>> f"result: {value:{width}.{precision}}"
'result:      12.35'

当然,它允许程序员编写绝对不可读的代码,但这不是目的:)

答案 2 :(得分:5)

我实际上只是遇到了类似的事情(我认为)并且认为我会分享。

我的具体情况是一个很大的脏sql语句,我需要有条件地有一些非常不同的值,但有些fstrings是相同的(并在其他地方也使用)。

以下是我的意思的快速示例。我选择的cols是相同的(并且也用于其他地方的其他查询)但是表名依赖于组而不是我可以在循环中执行它。

当我有多个这样的参数时,每次感觉有点脏时,必须在str2中包含mycols=mycols

我不确定这会起作用,但很高兴。至于它是如何pythonic我不是很确定tbh。

mycols='col_a,col_b'

str1 = "select {mycols} from {mytable} where group='{mygroup}'".format(mycols=mycols,mytable='{mytable}',mygroup='{mygroup}')

group = 'group_b'

if group == 'group_a':
    str2 = str1.format(mytable='tbl1',mygroup=group)
elif group == 'group_b':
    str2 = str1.format(mytable='a_very_different_table_name',mygroup=group)

print(str2)

答案 3 :(得分:3)

任何基本用例都是需要一个字符串来完全描述要放入f字符串大括号{}中的对象。例如,您需要字符串来索引字典。

因此,我最终在ML项目中使用了以下代码:

scores = dict()
scores[f'{task}_accuracy'] = 100. * n_valid / n_total
print(f'{task}_accuracy: {scores[f"{task}_accuracy"]}')

答案 4 :(得分:2)

在做一个宠物项目时,我写了我自己的数据库库,这使我无所适从。我发现的一件事是这样的:

>>> x = dict(a = 1, b = 2, d = 3)
>>> z = f"""
    UPDATE TABLE 
        bar 
    SET 
        {", ".join([ f'{k} = ?'     for k in x.keys() ])} """.strip()
>>> z
'UPDATE TABLE 
    bar 
SET 
    a = ?, b = ?, d = ?  '

我对此也感到惊讶,说实话,我不确定我是否会在生产代码中做这样的事情,但我也说过我不会在生产代码中做很多其他事情。

答案 5 :(得分:1)

我发现做三元组时嵌套很有用。您对可读性的看法会有所不同,但是我发现这种单行代码非常有用。

<div id="shadowBox">

  <h3 class="rainbow">VERB</h3>

</div>

这样,我的嵌套测试将是:

  • 该值是否已重用? (可用于表达式重用)
  • 表达清晰吗? (不超过复杂度)

答案 6 :(得分:1)

在 F-string 中,open-paren 和 close-paren 是保留键字符。 要使用 f-string 构建 json 字符串,您必须对括号字符进行转义。 在你的情况下只有外括号。

f"\{f'${price:0.2f}':*>20s\}"

答案 7 :(得分:1)

一个简单的例子,说明它何时有用,以及一个实现的例子:有时格式也是一个变量。

num = 3.1415
fmt = ".2f"
print(f"number is {num:{fmt}}")

答案 8 :(得分:1)

嵌套 f 字符串与格式说明符中的计算表达式

这个问题是关于在“外部”f 字符串的某些计算表达式中使用 f 字符串的用例。

这与允许计算表达式出现在 f 字符串的 within the format specifier 的功能不同。后一个功能非常有用并且与这个问题有些相关,因为(1)它涉及嵌套的花括号,所以这可能是人们查看这篇文章的原因,并且(2)在格式说明符中允许嵌套的 f 字符串,就像它们一样在 f 字符串的其他卷曲表达式中。

F-string 嵌套可以帮助单行

虽然肯定不是允许嵌套 f 字符串的动机,但在需要或想要“单行”(例如 lambda 表达式、推导式、{{1 }} 来自终端的命令)。例如:

python -c

如果您不需要单行,任何句法嵌套都可以通过之前定义一个变量然后在 f 字符串的计算表达式中使用变量名称来替换(在很多情况下,如果不是大多数情况,非-嵌套版本可能更具可读性和更易于维护;但是它确实需要提供变量名称):

print('\n'.join([f"length of {x/3:g}{'.'*(11 - len(f'{x/3:g}'))}{len(f'{x/3:g}')}" for x in range(10)]))

嵌套计算表达式(即在格式说明符中)很有用

与真正的 f 字符串嵌套相比,允许在 f 字符串的“格式说明符” 内评估表达式的相关功能非常有用(正如其他人指出的那样),原因有几个包括:

  1. 格式可以在多个 f 字符串或计算表达式之间共享
  2. 格式可以包括计算量,这些量会因运行而异

这是一个使用嵌套计算表达式的示例,但不是嵌套的 f 字符串:

for x in range(10):
    to_show = f"{x/3:g}"
    string_length = len(to_show)
    padding = '.' * (11 - string_length)
    print(f"length of {to_show}{padding}{string_length}")

然而,即使这种嵌套的使用也可以用不需要语法嵌套的更灵活(也许更干净)的代码代替:

import random

results = [[i, *[random.random()] * 3] for i in range(10)]
format = "2.2f"

print("category,precision,recall,f1")
for cat, precision, recall, f1 in results:
    print(f"{cat},{precision:{format}},{recall:{format}},{f1:{format}}")

答案 9 :(得分:-3)

你可以将它用于动态。例如,假设您将变量设置为某个函数的名称:

func = 'my_func'

然后你可以写:

f"{f'{func}'()}" 

这相当于:

'{}'.format(locals()[func]()) 

或等同于:

'{}'.format(my_func())