Black 代码风格的(未来)¶
预览风格¶
实验性的、可能具有破坏性的风格更改被收集在 --preview
CLI 标志下。在每年的年底,这些更改可能会被采用到默认风格中,如 Black 代码风格 中所述。由于该功能是实验性的,因此鼓励反馈和问题报告!
在过去,预览风格包含了一些已知有 bug 的功能,因此我们无法将这些功能迁移到稳定风格中。因此,此类功能现在已被迁移到 --unstable
风格中。--preview
风格中的所有功能预计将在下一年的稳定风格中发布;--unstable
风格中的功能只有在修复了其问题后才会被稳定。如果在 --preview
功能中发现了 bug,它将降级到 --unstable
风格中。为了避免在功能从 --preview
降级到 --unstable
风格时出现混乱,用户可以使用 --enable-unstable-feature
标志来启用特定的不稳定功能。
目前,预览风格中包含以下功能
hex_codes_in_unicode_sequences
:规范化字符串中 Unicode 转义字符的大小写unify_docstring_detection
:修复某些字符串是否被检测为文档字符串的不一致性no_normalize_fmt_skip_whitespace
:# fmt: skip
注释之前的空白不再被规范化typed_params_trailing_comma
:始终为类型化的函数参数添加尾部逗号is_simple_lookup_for_doublestar_expression
:修复某些包含幂运算符的表达式的行长计算docstring_check_for_newline
:检查文档字符串的结束引号之前是否有换行符remove_redundant_guard_parens
:删除case
块的if
保护中的冗余括号。parens_for_long_if_clauses_in_case_block
:当行过长时,为case
块中的if
子句添加括号
不稳定风格还包含以下功能
string_processing
:分割长字符串文字和相关更改(见下文)wrap_long_dict_values_in_parens
:在字典中添加长值的括号(见下文)multiline_string_handling
:更紧凑地格式化涉及多行字符串的表达式(见下文)hug_parens_with_braces_and_square_brackets
:更紧凑地格式化嵌套括号(见下文)
为唯一的函数参数改进多行字典和列表缩进¶
为了提高可读性和减少垂直性,*Black* 现在将括号(“(”, “)”)与大括号(“{”, “}”)和方括号(“ [”, “]”)放在同一行上。例如
foo(
[
1,
2,
3,
]
)
nested_array = [
[
1,
2,
3,
]
]
将更改为
foo([
1,
2,
3,
])
nested_array = [[
1,
2,
3,
]]
这也适用于列表和字典解包
foo(
*[
a_long_function_name(a_long_variable_name)
for a_long_variable_name in some_generator
]
)
将变为
foo(*[
a_long_function_name(a_long_variable_name)
for a_long_variable_name in some_generator
])
你可以使用魔术尾部逗号来避免这种压缩行为;默认情况下,*Black* 不会重新格式化以下代码
foo(
[
1,
2,
3,
],
)
改进的字符串处理¶
*Black* 将分割长字符串文字并合并短字符串文字。在适当的情况下使用括号。当分割时,不需要格式化的 f-字符串的部分将转换为普通字符串。当用户创建的分割不超过行长限制时,这些分割将被保留。行延续反斜杠将被转换为带括号的字符串。不必要的括号将被删除。此功能的稳定性和状态在 此问题 中跟踪。
字典中改进的括号管理¶
对于具有长值的字典文字,现在它们将被包裹在括号中。现在将删除不必要的括号。例如
my_dict = {
"a key in my dict": a_very_long_variable
* and_a_very_long_function_call()
/ 100000.0,
"another key": (short_value),
}
将更改为
my_dict = {
"a key in my dict": (
a_very_long_variable * and_a_very_long_function_call() / 100000.0
),
"another key": short_value,
}
改进的多行字符串处理¶
*Black* 在格式化多行字符串时更加智能,尤其是在函数参数中,以避免引入额外的换行符。以前,它总是将多行字符串视为无法放在一行上。有了这个新功能,*Black* 会查看多行字符串周围的上下文,以决定是将其内联还是拆分到单独的行上。例如,当将多行字符串传递给函数时,*Black* 只有在行过长或传递了多个参数时才会分割多行字符串。
例如,*Black* 将重新格式化
textwrap.dedent(
"""\
This is a
multiline string
"""
)
为
textwrap.dedent("""\
This is a
multiline string
""")
以及
MULTILINE = """
foobar
""".replace(
"\n", ""
)
为
MULTILINE = """
foobar
""".replace("\n", "")
隐式多行字符串是特殊的,因为它们可以包含内联注释。没有注释的字符串将被合并,例如
s = (
"An "
"implicit "
"multiline "
"string"
)
变为
s = "An implicit multiline string"
字符串的任何行上的注释(或两个字符串行之间)将阻止合并,因此
s = (
"An " # Important comment concerning just this line
"implicit "
"multiline "
"string"
)
以及
s = (
"An "
"implicit "
# Comment in between
"multiline "
"string"
)
将不会被合并。在字符串行之后或之前(但仍然在括号内)添加注释将合并字符串。例如
s = ( # Top comment
"An "
"implicit "
"multiline "
"string"
# Bottom comment
)
变为
s = ( # Top comment
"An implicit multiline string"
# Bottom comment
)
潜在的未来更改¶
本节列出我们可能希望在未来进行的更改,但尚未实施。
使用反斜杠进行 with 语句¶
反斜杠很糟糕,永远不应该使用,但是有一个例外:使用多个上下文管理器进行的 with
语句。在 Python 3.9 之前,Python 的语法不允许在上下文管理器序列周围组织括号。
我们不希望格式化成
with make_context_manager1() as cm1, make_context_manager2() as cm2, make_context_manager3() as cm3, make_context_manager4() as cm4:
... # nothing to split on - line too long
因此,当我们实施此功能时,*Black* 将格式化成这样
with \
make_context_manager1() as cm1, \
make_context_manager2() as cm2, \
make_context_manager3() as cm3, \
make_context_manager4() as cm4 \
:
... # backslashes and an ugly stranded colon
虽然当目标版本为 Python 3.9 或更高版本时,*Black* 在 --preview
模式下(见下文)使用括号,因为它们在 Python 3.9 及更高版本中是允许的。
如果上述格式中的反斜杠不可取,可以考虑的替代方案是使用 contextlib.ExitStack
以以下方式组合上下文管理器
with contextlib.ExitStack() as exit_stack:
cm1 = exit_stack.enter_context(make_context_manager1())
cm2 = exit_stack.enter_context(make_context_manager2())
cm3 = exit_stack.enter_context(make_context_manager3())
cm4 = exit_stack.enter_context(make_context_manager4())
...