嵌套 f 字符串的用例有哪些[关闭]

2025-04-16 08:56:00
admin
原创
19
摘要:问题描述:感谢David Beazley 的推文,我最近发现新的Python 3.6 f 字符串也可以嵌套:>>> price = 478.23 >>> f"{f'${price:0.2f}':*>20s}" '*************$478....

问题描述:

感谢David Beazley 的推文,我最近发现新的Python 3.6 f 字符串也可以嵌套:

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

或者:

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

虽然我很惊讶这是可能的,但我不明白这有多实用,嵌套 f 字符串什么时候有用?它能涵盖哪些用例?

注意:PEP 本身没有提到嵌套 f 字符串,但有一个特定的测试用例。


解决方案 1:

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

规范声明它们支持括号内的完整 Python表达式。规范还指出,格式化字符串字面量实际上只是一个*在运行时求值的表达式(参见此处和此处)。因此,允许一个格式化字符串字面量作为另一个格式化字符串字面量中的表达式才是合理的;禁止这样做将否定对 Python 表达式的完全支持。

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


*实际上,有三个例外:

  1. 不允许出现空表达式。

  2. Lambda 表达式必须被明确的括号括起来。

  3. 使用相同的引号嵌套字符串会导致语法错误。

解决方案 2:

我猜这是为了在同一行传递格式化参数,从而简化f 字符串的使用。

例如:

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

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

解决方案 3:

事实上,我刚刚遇到过类似的事情(我认为)并想分享一下。

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

以下是我所指的简单示例。无论如何,我选择的列都是相同的(并且也用于其他查询中),但是表名取决于组,因此我无法在循环中执行此操作。

当我有多个这样的参数时,每次都必须将其包含mycols=mycols在 str2 中,这感觉有点麻烦。

我之前不确定这是否可行,但很高兴它成功了。至于它有多 Pythonic,说实话我不太确定。

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)

解决方案 4:

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

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

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

解决方案 5:

我用它来格式化货币。给定如下值:

a=1.23
b=45.67

使用 $ 开头的格式,并将小数点对齐。例如

 $1.23
$45.67

使用单个 f 字符串进行格式化,f"${value:5.2f}"您可以获得:

$ 1.23
$45.67

有时候这样没问题,但并不总是如此。嵌套的 f 字符串f"{f'${value:.2f}':>6}"会提供精确的格式:

 $1.23
$45.67

当您想在数字中添加其他单位符号时,它同样有用,例如#

解决方案 6:

我发现嵌套在处理三元运算符时很有用。关于可读性,大家的看法可能有所不同,但我发现这行代码非常有用。

logger.info(f"No program name in subgroups file. Using {f'{prg_num} {prg_orig_date}' if not prg_name else prg_name}")

因此,我对嵌套的测试将是:

  • 该值是否被重用?(表达式重用的变量)

  • 表达清楚吗?(不超过复杂度)

解决方案 7:

在 Python 3.12 之前,嵌套 f 字符串受限于字符串解析的限制。例如,f'{f""}'是有效的,而f'{f"{f''}"}'会导致SyntaxError。因此,f 字符串最多只能嵌套四次(使用',"以及它们各自的三重引号)。

由于 f 字符串不遵循 Python 的常规语法,这看起来有些武断、不一致且违反直觉。因此,随着 Python 3.12 的推出,此类限制已被取消,从而使示例表达式变得有效。此更改的其他动机在PEP 701f'{f"{f''}"}'中有进一步概述。

解决方案 8:

嵌套的 f 字符串与格式说明符中的求值表达式

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

这与允许求值表达式出现在 f 字符串的格式说明符内的功能不同。后者非常有用,并且与这个问题有一定关联,因为 (1) 它涉及嵌套的花括号,所以这可能是人们阅读这篇文章的原因;(2) 格式说明符内允许嵌套的 f 字符串,就像它们在 f 字符串的其他花括号表达式中一样。

F 字符串嵌套有助于单行代码

虽然嵌套 f 字符串并非出于允许使用嵌套 f 字符串的动机,但在一些不太常见的情况下,例如需要或想要“一行代码”(例如 lambda 表达式、推导式、python -c终端命令),嵌套可能会有所帮助。例如:

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

如果您不需要单行代码,则可以通过预先定义一个变量,然后在 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}")

嵌套求值表达式(即格式说明符)很有用

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

  1. 格式可以在多个 f 字符串或求值表达式之间共享

  2. 格式可以包括每次运行都可能变化的计算量

下面是一个使用嵌套求值表达式但不使用嵌套 f 字符串的示例:

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}}")

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

import random

results = [[i, *[random.random()] * 3] for i in range(10)]
def format(x):
    return f"{x:2.2f}"

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

解决方案 9:

我在做一个自己喜欢的项目时,因为编写自己的数据库库而分心了。我发现了以下事情:

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

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

解决方案 10:

在 F 字符串中,左括号和右括号是保留键字符。要使用 F 字符串构建 json 字符串,必须转义括号字符。在本例中,只需要转义最外层的括号即可。

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

解决方案 11:

以下嵌套的 f 字符串单行代码在构造命令参数字符串方面做得很好

cmd_args = f"""{' '.join([f'--{key} {value}' for key, value in kwargs.items()])}"""

输入
{'a': 10, 'b': 20, 'c': 30, ....}

优雅地转换为
--a 10 --b 20 --c 30 ...
`

解决方案 12:

Selenium 测试验证网页上的文本是否根据动态数据输入以特定方式读取。

weeks: Literal[1,2,3,4,5,6] | None
rotation = f"Rotation:
{f'{weeks} weeks' if weeks else 'Add rotation'}"

解决方案 13:

我曾在这样的单行情况下使用过它:

s = 2.1
print(f"{f'Is {s} an int? {"True" if isinstance(s, int) else "False"}':>25}")

# Instead of having to combine with other string manipulating methods:
print(f"Is {s} an int? {"True" if isinstance(s, int) else "False"}".rjust(25))

在此处输入图片描述

解决方案 14:

我发现这个问题是关于如何使用空格填充而不是零填充的十进制数字(参见https://strftime.org/)来格式化月份和日期。

dt = datetime.strptime('2024 1 3 1501', '%Y %m%d %H%M')

# simple formatting with month and day as zero-padded decimal numbers
print(f"{dt:%Y %m %d %H%M}")
# 2024 01 03 1501

# no padding 
print(f"{dt:%Y %-m %-d %H%M}")
# 2024 1 3 1501

# left padding with space (space-padded but aligns with 0-padded)
print(f"{dt:%Y {f'{dt:%-m}':>2} {f'{dt:%-d}':>2} %H%M}")
# 2024  1  3 1501

另请参阅如何格式化日期并用空格填充?中的示例。

# format date (no padding)
print(f"{today:%d-%m-%Y}")
# 19-05-2024

# nested f-string
print(f"{f'{today:%d-%m-%Y}':>20}")
#           19-05-2024

解决方案 15:

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

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

解决方案 16:

如果需要一些奇特的格式,这种嵌套可能会有用。

for n in range(10, 1000, 100):
    print(f"{f'n = {n:<3}':<15}| {f'|{n:>5}**2 = {n**2:<7_}'} |")

解决方案 17:

你可以用它来实现动态性。比如,假设你有一个变量,设置为某个函数的名称:

func = 'my_func'

然后你可以写:

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

这相当于:

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

或者,等效地:

'{}'.format(my_func())
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2482  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1533  
  PLM(产品生命周期管理)项目对于企业优化产品研发流程、提升产品质量以及增强市场竞争力具有至关重要的意义。然而,在项目推进过程中,范围蔓延是一个常见且棘手的问题,它可能导致项目进度延迟、成本超支以及质量下降等一系列不良后果。因此,有效避免PLM项目范围蔓延成为项目成功的关键因素之一。以下将详细阐述三大管控策略,助力企业...
plm系统   0  
  PLM(产品生命周期管理)项目管理在企业产品研发与管理过程中扮演着至关重要的角色。随着市场竞争的加剧和产品复杂度的提升,PLM项目面临着诸多风险。准确量化风险优先级并采取有效措施应对,是确保项目成功的关键。五维评估矩阵作为一种有效的风险评估工具,能帮助项目管理者全面、系统地评估风险,为决策提供有力支持。五维评估矩阵概述...
免费plm软件   0  
  引言PLM(产品生命周期管理)开发流程对于企业产品的全生命周期管控至关重要。它涵盖了从产品概念设计到退役的各个阶段,直接影响着产品质量、开发周期以及企业的市场竞争力。在当今快速发展的科技环境下,客户对产品质量的要求日益提高,市场竞争也愈发激烈,这就使得优化PLM开发流程成为企业的必然选择。缺陷管理工具和六西格玛方法作为...
plm产品全生命周期管理   0  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用