rcmdnk's blog

少しかしこくなれる数式の話

Pythonで長い行を改行して書きたいとき、式などで+andなどの演算子が混じってるときは その前後で改行することが多いと思いますが、 その際に改行を演算子の前にするのか、後にするのか、は迷うところです。

これに関してPythonのコーディング規約であるPEP 8では改行は演算子の前にすることを推奨しています。 ただ、実はこれは2016年頃に変わったもので、それ以前は逆に改行は演算子の後にすることが推奨されていました。

Sponsored Links

PEP 8による改行を演算子の前後どちらでするか、の定義

演算子の後で改行をする、というのは以下の様なケース。

abc = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +
       bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +
       ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc) *\
    ddd

これだと+の後で改行が行われています。 一方、

abc = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
       + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
       + ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc)\
    * ddd

だと改行後、演算子から新しい行が始まっています。

これに関して以下に記述があります。

Should a Line Break Before or After a Binary Operator?

はじめに — pep8-ja 1.0 ドキュメント

演算子が行の最後に来ることで、演算子の場所がバラバラになることと、 その演算子がかかる項目(次に来る変数/数字)との距離が離れてパット見わかりにくくなる、 という弊害がある、とのこと。

一方数学論文などでは文章中の数式であれば演算子の後に改行するが 別行立て(LaTexでいうディスプレイ数式の様な)の場合には改行の後に数式を置くようにしている、ということで これに従ったほうが良いだろう、となったようです。

上のケースを見てみると、確かに下の方が+に位置が揃っていて見やすい感じがするし、 最後の* ddddddは全体への掛け算で使われるのだな、ということがすぐにわかります。

もちろん場合によっては上の方が良いやすい場合もあります。 例えば上の例でもカッコ内が全て足されるだけ、とわかっているなら最初の項だけ特別扱いする様な下の書き方より 上の方が統一的、ともいえます。

とはいえ、こういった書き方を良くする数学の論文では下の様な書き方を採用しているのだから おそらく多くの場合は下の方が見やすいのでしょう、ということだと思います。

Flake8での定義

PythonのリントツールであるFlake8では 以下の様な2つのWarningの定義があります。

Line break occurred before a binary operator (W503)

Line break occurred after a binary operator (W504)

W503は改行が演算子の前に来ていることを注意するもの、 W504は改行が演算子の後に来ていることを注意するもの。

つまりこれらは矛盾していて、両方を満たすためには演算子の前後で改行をしない様にしなくてはいけません。

Flake8では決してそういった改行両方するな、ということを推奨しているわけではなく、 もともとW503があったところに 途中(2016年)からPEP 8の定義が変わったため逆を注意するW504を作ったという感じです。

とはいってもFlake8の履歴を見る限り、W504の方に対応したのは2018年頃で、 この頃から両方をチェックしてどうしたってwarningになって困る、 みたいな議論はあったみたいです。

W503.md: History for _rules/W503.md - LintlyCI/Flake8Rules

W504.md: History for _rules/W504.md - LintlyCI/Flake8Rules

現状ではどちらかをデフォルトでなくす、ということはせず、必要な方をignoreする、という方針にしています。

現在のPEP 8に従うのであれば、

$ flake8 gfm.py  --ignore=W503

としてW503を無視します。

もしくは~/.config/flake8

[flake8]
ignore=W503

と書いて設定しておきます。これでW503の方が無視されるようになります。

blackでの定義

最近話題?のフォーマッターであるblackでは 改行後に演算子を置くようにフォーマットされる様になっています。に

上の

abc = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +
       bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +
       ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc) *\
    ddd

をblackにかければ

abc = (
    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
    + ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
) * ddd

の様に変わります。

まとめ

Pythonでの演算子と改行の位置、についての話でしたが、 基本的には他の言語でも同じことが言えます。

確かに式として本や論文に載っているとき、複数行に渡る時には 演算子が前側で揃っていることがほとんどでそれの方が見やすいと思います。

なのでPythonでも他の言語でもその方が見やすいことが多いはずです。

なんとなく長年適当にいつもどっちかな、と毎回思いながらやっていた部分ですが 今後は気をつけて行きたいところです。

Sponsored Links
Sponsored Links

« GNU Screen 4.7.0リリース GitHub Sponsorsがベータが外れ全てのユーザーが使えるように »