在自记录 f 字符串中的等号后插入换行符

Eni*_*ine 5 python string f-string

在 python3.8 中,一个新功能是自记录格式字符串。人们通常会这样做:

>>> x = 10.583005244
>>> print(f"x={x}")
x=10.583005244
Run Code Online (Sandbox Code Playgroud)

现在可以减少重复次数来做到这一点:

>>> x = 10.583005244
>>> print(f"{x=}")
x=10.583005244
Run Code Online (Sandbox Code Playgroud)

这对于单行字符串表示非常有效。但请考虑以下场景:

>>> import numpy as np
>>> some_fairly_long_named_arr = np.random.rand(4,2)
>>> print(f"{some_fairly_long_named_arr=}")
some_fairly_long_named_arr=array([[0.05281443, 0.06559171],
       [0.13017109, 0.69505908],
       [0.60807431, 0.58159127],
       [0.92113252, 0.4950851 ]])
Run Code Online (Sandbox Code Playgroud)

在这里,第一行没有对齐,这(可以说)是不可取的。我更喜欢以下输出:

>>> print(f"some_fairly_long_named_arr=\n{some_fairly_long_named_arr!r}")
some_fairly_long_named_arr=
array([[0.05281443, 0.06559171],
       [0.13017109, 0.69505908],
       [0.60807431, 0.58159127],
       [0.92113252, 0.4950851 ]])
Run Code Online (Sandbox Code Playgroud)

在这里,输出的第一行也对齐了,但是它违背了在 print 语句中不重复变量名称两次的目的。

该示例是一个 numpy 数组,但它也可能是一个 pandas 数据框等。

=因此,我的问题是:可以在自记录字符串的符号后面插入换行符吗?

我尝试像这样添加它,但它不起作用:

>>> print(f"{some_fairly_long_named_arr=\n}")
SyntaxError: f-string expression part cannot include a backslash
Run Code Online (Sandbox Code Playgroud)

我阅读了format-specation-mini-language 上的文档,但其中的大多数格式仅适用于整数等简单数据类型,并且我无法使用那些有效的数据类型来实现我想要的效果。

Eni*_*ine 0

Python 3.12+

Python 3.12 引入了f 字符串的语法形式化,它允许嵌套 f 字符串。这允许我们使用以下构造来实现我们想要的。

NL = '\n'
print(f"{f"{NL}{some_fairly_long_named_arr}" = !s}")
Run Code Online (Sandbox Code Playgroud)

哪个输出:

f"{NL}{some_fairly_long_named_arr}" =
[[0.26616956 0.59973262]
 [0.86601261 0.10119292]
 [0.94125617 0.9318651 ]
 [0.10401072 0.66893025]]
Run Code Online (Sandbox Code Playgroud)

Python<3.12

多线解决方案

在阅读了CPython 源代码后,我找到了一种实现我想要的方法:

import numpy as np
some_fairly_long_named_arr = np.random.rand(4, 2)
print(f"""{some_fairly_long_named_arr =
}""")
Run Code Online (Sandbox Code Playgroud)

其产生:

some_fairly_long_named_arr = 
array([[0.23560777, 0.96297907],
       [0.18882751, 0.40712246],
       [0.61351814, 0.1981144 ],
       [0.27115495, 0.72303859]])
Run Code Online (Sandbox Code Playgroud)

我更喜欢在单行中工作的解决方案,但这似乎是目前唯一的方法。也许以后的Python版本会实现另一种方式。

但请注意,对于上述方法,必须删除续行上的缩进,如下所示:

    # ...some code with indentation...
    print(f"""{some_fairly_long_named_arr =
}""")
    # ...more code with indentation...
Run Code Online (Sandbox Code Playgroud)

否则,第一行的对齐方式将再次被破坏。

我尝试使用inspect.cleandoctextwrap.dedent来缓解这个问题,但无法解决缩进问题。但也许这是另一个问题的主题。

单线解决方案

读完这篇文章后我发现了这一点:

f_str_nl = lambda object: f"{chr(10) + str(object)}"  # add \n directly
# f_str_nl = lambda object: f"{os.linesep + str(object)}"  # add \r\n on windows

print(f"{f_str_nl(some_fairly_long_named_arr) = !s}")
Run Code Online (Sandbox Code Playgroud)

其输出:

f_str_nl(some_fairly_long_named_arr) = 
[[0.26616956 0.59973262]
 [0.86601261 0.10119292]
 [0.94125617 0.9318651 ]
 [0.10401072 0.66893025]]
Run Code Online (Sandbox Code Playgroud)

唯一需要注意的是,对象的名称前面加上了自定义 lambda 函数的名称f_str_nl

我还发现这里已经提出了类似的问题。