Pythonのインデント系エラーと戦う


このエントリーをはてなブックマークに追加

Pythonスクリプトを書いてflake8にかけると、インデント量や改行タイミングの微妙な違反によって

  • E125 continuation line with same indent as next logical line
  • E129 visually indented line with same indent as next logical line

といったエラーが出ます。エラー例と直し方の例をまとめていきます。

例1

def function_having_very_long_name(
    arg_having_very_very_very_very_very_very_very_long_name):
    pass

関数名・引数名の両方が長いときは、上記のように(の直後で改行を入れたくなります。 しかしこのコードにflake8をかけると

E125 continuation line with same indent as next logical line

と怒られます。

直し方は以下があります。

直し方1

def function_having_very_long_name(
        arg_having_very_very_very_very_very_very_very_long_name):
    pass

引数を4個後ろにずらす方法です。yapfやautopep8というフォーマッタはこう直しました。

直し方2

def function_having_very_long_name(
    arg_having_very_very_very_very_very_very_very_long_name,
):
    pass

これはblackというフォーマッタの直し方です。引数の最後に','が追加されていますがこれはblackの趣味だと思います。

例2

ifの条件部分がとても長い場合を考えます。

a = b = c = d = e = f = g = h = 100
if (a == 100 and b == 200 and c == 300 and d == 400 and
    e == 500 and f == 500 and g == 600 and h == 700):
    print("ok")

と改行して書きたくなりますが、これをflake8にかけると

E129 visually indented line with same indent as next logical line

とエラーが出てしまいます。e == 200print('ok')の文頭の位置が揃ってしまったのが原因です。

このエラーは遭遇する人が多いようで、 https://stackoverflow.com/q/181530E125 overreaches pep8 · Issue #126 · PyCQA/pycodestyle でいろんな直し方の議論があります。

今回はフォーマッタにお伺いを立てました。

直し方1

a = b = c = d = e = f = g = h = 100
if (a == 100 and b == 200 and c == 300 and d == 400 and
        e == 500 and f == 500 and g == 600 and h == 700):
    print("ok")

e == 500の部分を4つ後ろにずらす方法です。autopep8はこの方法をとりました。私も多分こうすると思います。

yapfの結果も似ていますが、改行の位置を勝手にいじりました。

a = b = c = d = e = f = g = h = 100
if (a == 100 and b == 200 and c == 300 and d == 400 and e == 500 and f == 500
        and g == 600 and h == 700):
    print("ok")

直し方2

blackは、以下のように条件部をすべて縦に並べるよう整形しました。一貫性はありますが、無駄に行数を使うのが嫌です。

a = b = c = d = e = f = g = h = 100
if (
    a == 100
    and b == 200
    and c == 300
    and d == 400
    and e == 500
    and f == 500
    and g == 600
    and h == 700
):
    print("ok")