在python3.8中自文档化f字符串的等号后插入换行符

tez616oj  于 2023-01-08  发布在  Python
关注(0)|答案(2)|浏览(113)

在python3.8中,一个新特性是自文档化格式字符串,通常是这样做的:

>>> x = 10.583005244
>>> print(f"x={x}")
x=10.583005244
>>>

现在可以这样做,而无需重复:

>>> x = 10.583005244
>>> print(f"{x=}")
x=10.583005244
>>>

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

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

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

>>> import numpy as np
>>> some_fairly_long_named_arr = np.random.rand(4,2)
>>> print(f"some_fairly_long_named_arr=\n{some_fairly_long_named_arr!r}")
some_fairly_long_named_arr=
array([[0.06278696, 0.04521056],
       [0.33805303, 0.17155518],
       [0.9228059 , 0.58935207],
       [0.80180669, 0.54939958]])
>>>

在这里,输出的第一行也是对齐的,但是它破坏了在print语句中不重复变量名两次的目的。
这个例子是一个numpy数组,但是它也可以是一个panda Dataframe 等等。
因此,我的问题是:可以在自文档化字符串中的=符号后插入换行符吗?
我试着像这样添加它,但它不起作用:

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

我读了关于格式规范迷你语言的文档,但是那里的大多数格式只适用于简单的数据类型,比如整数,我无法使用那些有效的格式来实现我想要的。
抱歉写了这么长。

wnavrhmk

wnavrhmk1#

完全不推荐这样做,但为了可能性起见:

import numpy as np

_old_array2string = np.core.arrayprint._array2string

def _array2_nice_string(*args, **kwargs):
    non_nice_string = _old_array2string(*args, **kwargs)

    dimension_strings = non_nice_string.split("\n")

    if len(dimension_strings) > 1:
        dimension_string = dimension_strings[1]
        dimension_indent = len(dimension_string) - len(dimension_string.lstrip())

        return "\n" + " " * dimension_indent + non_nice_string

    return non_nice_string

np.core.arrayprint._array2string = _array2_nice_string

输出:
x一个一个一个一个x一个一个二个x
以及

some_fairly_long_named_arr = np.random.rand(1, 2)
print(f"{some_fairly_long_named_arr=}")

some_fairly_long_named_arr=array([[0.62492772, 0.80453153]]).
我把它设成如果第一维是1,它保持在同一条线上。
有一个非内部方法np.array2string,我尝试过重新赋值,但是我从来没有让它工作过。如果有人能找到一种方法来重新赋值那个公共函数,而不是这个内部使用的函数,我想这会让这个解决方案更简洁。

xdnvmnnf

xdnvmnnf2#

在通读了CPython source之后,我找到了一种方法来实现我想要的:

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.23560777, 0.96297907],
       [0.18882751, 0.40712246],
       [0.61351814, 0.1981144 ],
       [0.27115495, 0.72303859]])

我宁愿选择一个在单行中工作的解决方案,但这似乎是目前唯一的方法,也许另一种方法将在以后的python版本中实现。
但是,请注意,对于上述方法,必须删除续行上的缩进,如下所示:

# ...some code with indentation...
    print(f"""{some_fairly_long_named_arr =
}""")
    # ...more code with indentation...

否则,第一行的对齐将再次中断。
我尝试使用inspect. cleandoc和textwrap. dedent来缓解这个问题,但是无法修复缩进问题。
编辑:看完this article后,我发现了一个单线解决方案:

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

其输出:

f_str_nl(some_fairly_long_named_arr) = 
[[0.26616956 0.59973262]
 [0.86601261 0.10119292]
 [0.94125617 0.9318651 ]
 [0.10401072 0.66893025]]

唯一需要注意的是,对象的名称前面要加上自定义lambda函数的名称f_str_nl
我还发现类似的问题已经问过here了。

相关问题