Python
バッドノウハウ
ポエム

Pythonの改行が文法以外の理由で必要な状況をなんとかする

前説

Pythonでは、通常if等は改行することになっていますが、単純文であれば改行しなくても書くことができます。
https://docs.python.org/ja/3/reference/compound_stmts.html
(なおif等のネストは改行しないと書けないので、本当の意味でのワンライナーはPythonでは不可能です)

十分短い場合など、改行しないほうが読みやすい場合もあると思います。
が、改行することが規約等で定められている場合もあると思います。
そのような場合に、改行を避ける手段を紹介していきます。
一部バッドノウハウを含みます。

関数

def func(a): return a.attr
  • lambdaはどこに書こうと構いません。
    • func=lambda a:a.attr

ファイル書き込み

with open('a.txt','w') as f: f.write(s)
  • そのままwithを潰します。

    • open('a.txt','w').write(s)
    • GCされるまでファイルが閉じられなくなります。ご注意ください。
  • 読み込みも同様ですが、代入が入るので好みの事情が違ってきそう。

if

条件return(等)

if cls is None: return None
return cls.attr
  • 3項演算子にするか。
    • return None if cls is None else cls.attr
  • インスタンス変数であれば偽な値はNoneぐらいじゃないでしょうか。
    • return cls and cls.attr

短絡return

if not pred: return None
(処理)
return val

短絡させなければよいのです。

if pred:
    (処理)
    return val
# 関数の終わりで暗黙的にNoneが返される

for

逐次処理

  • 単純なところで、set1に含まれている要素をset2から取り除く処理。
for e in set1: set2.remove(e)
  • リスト内包表記にします。
    • [set2.remove(e) for e in set1]
    • 代入を伴わないリスト内包表記 となります。ご注意ください。
    • 個人的に気持ち悪いんですが、どうでしょうか。

ジェネレータ移譲

for e in generator(): yield e
  • Python3.3で導入されたyield fromを使えばfor文なしにジェネレータを移譲できます。ただしPython2では使えません。
    • yield from generator()
  • forの後ろに処理が続かないのであれば、ジェネレータを直接返すことができます。
    • return generator()
    • https://stackoverflow.com/a/11197219
    • ただし、移譲関数が(inspect.isgeneratorfunction等で)ジェネレータかどうかを判別している場合はこちらは使えません。 pytestとか。

あえてコードを長くする

逆のやり方となりますが、関数内関数を持ち出すなどして意図的にインデントを深くし、改行しないほうが読みやすい状況を潰します。

def func(...):
   def removeset2ifinset1(set1,set2):
       for e in set1:
           set2.remove(e)
   (処理)
   removeset2ifinset1(set1,set2)

当該処理が複数ヶ所に出てくるなら許容範囲、一箇所だけならご注意な気がしています。

最後に

あとで追加するかも。

以上、単なるポエムでした。実行して被った被害に対する責任は負いません。