Pythonの例外ハンドラはローカル変数のスコープを破壊する

dev.thanaism.com

pythonはやばい。理解に苦しむ挙動が多くてつらい。たとえば以下のコード

def inverse(a):
    if a == 0:
        raise ValueError('0で割ることはできません')
    return 1 / a

def main():
    e = 0
    try:
        e = inverse(2)
    except ValueError as e:
        print(e.args[0])

    print(e)

main()

これは何と出力されるでしょうか?

0.5

となります。これは問題ありません

ではmainをこうするとどうでしょう

def main():
    e = 0
    try:
        e = inverse(0)
    except ValueError as e:
        print(e.args[0])

    print(e)

inverse(0)が例外を投げるので、以下のように出力されると予想するのではないでしょうか

0で割ることはできません
0

違います、実際はこうなります

0で割ることはできません
Traceback (most recent call last):
  File "/Users/hisanori/hoge.py", line 17, in <module>
    main()
  File "/Users/hisanori/hoge.py", line 15, in main
    print(e)
          ^
UnboundLocalError: cannot access local variable 'e' where it is not associated with a value

未定義のローカル変数エラーが発生しました。関数内で定義したローカル変数と同じ名前の変数を例外ハンドラに使用し、実際に例外がスローされた場合、元のローカル変数の定義がなかった事にされてしまっています。例外発生時だけこんなエラーを出すなら例外が発生していない時も同じエラーにしてほしい・・・

JavaやJSなどでは例外ハンドラで新しいスコープが作られるので元のeと例外ハンドラのeは別の変数となり予想通りエラーメッセージと0が出力されます。Rubyの場合は例外ハンドラが新しいスコープを作らないらしくエラーメッセージが2回でます。

という感じに他の言語で培った常識が通じなかったりして、pythonにはあまり深入りしたくないという気持ちが強い

自炊

恐ろしい。なぜ日本人は自ら人生をハードモードに設定してもがき苦しむのか。アメリカではレンチンは重労働というのが常識であり、冷凍餃子をフライパンで焼くなどしようものなら君はとても料理が得意なんだね!と褒められるであろう

togetter.com

そもそも、自分にとって自炊という言葉は「貧乏学生や限界独身中高年による外食以外の栄養摂取行為」と定義されるものである。よって自炊とは以下のような食事を指す

  • ご飯と納豆と味噌汁のみの食事
  • 具なし袋ラーメンを鍋のまま食べる
  • 冷凍チャーハンをレンチン
  • 卵かけご飯
  • パンにマーガリンを塗ってハムを乗せて焼く
  • コーンフレークに牛乳をかける

これらは全て自炊である。フライパンと油が必要な冷凍餃子など手間暇かかったエクストリームでハイエンドな自炊なのである

逆に手作り餃子のような高尚な行為を自炊とは呼ばない。また自分以外のニンゲンにも食べさせるために作るのも自炊ではない。これらはただ栄養摂取のみを目的とした行為ではないからである