Blackコードスタイルの(将来の)姿

プレビュースタイル

実験的で、場合によっては破壊的なスタイルの変更は、--preview CLIフラグの下に集められます。毎年年末に、これらの変更はBlackコードスタイルで説明されているように、デフォルトのスタイルに採用される可能性があります。この機能は実験的なため、フィードバックやIssueレポートを強く推奨します!

過去には、プレビュースタイルには既知のバグのある機能が含まれており、これらの機能を安定版スタイルに移行できませんでした。したがって、そのような機能は--unstableスタイルに移動されました。--previewスタイルのすべての機能は、来年の安定版スタイルになることが期待されています。--unstableスタイルの機能は、それらの問題が修正された場合にのみ安定化されます。--preview機能でバグが発見された場合、--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-stringの一部は、プレーン文字列に変換されます。ユーザーが作成した分割は、行の長さの制限を超えない限り尊重されます。行継続バックスラッシュは、括弧で囲まれた文字列に変換されます。不要な括弧は削除されます。この機能の安定性とステータスは、このIssueで追跡されます。

辞書における改善された括弧の管理

長い値を持つ辞書リテラルの場合、括弧で囲まれるようになりました。不要な括弧は削除されます。例えば

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は、特に関数引数における複数行文字列のフォーマット時に、余分な改行を導入しないように、より賢くなりました。以前は、常に複数行文字列が1行に収まらないと見なしていました。この新しい機能では、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"

文字列の任意の行(または2つの文字列行の間)にあるコメントはマージをブロックするため、

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ステートメントにバックスラッシュを使用する

バックスラッシュは悪であり、絶対に使用すべきではありません。ただし、1つの例外があります。それは、複数のコンテキストマネージャーを使用する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())
    ...