Kaggle Advent Calendar の12日目の記事です。
こんにちは。fkubotaです。今はKaggle Expertです。
さっそくですが、Jupyter Notebook で作業をしている時、グローバル変数に困らされたことはないでしょうか?
僕は業務でもKaggleでもNotebook上で作業をすることが多々あるのですが、結構な頻度で意図しないグローバル変数が原因のバグに出会います。
そこで以下のTweetをしてみました。これが事の始まりです。
aaa = 1
— fkubota 🦉 (@the_phi_is_cast) December 6, 2020
def hoge(b):
c = aaa + b
return c
print(hoge(2))
↑これ動くの嫌なんですが、どうにかしてエラー吐かせるようにできないですか?
与えた引数の変数しか使えないようにしたいです…
こういったこと、クラスとか使ってちゃんと書いた.pyのスクリプトだと起こらない自体ですよね。
Jupyter Notebookは便利ですが、こういったことが原因のバグを埋め込んでしまうことがあります。
これを避けるには、notebookを使わないという選択肢もありますが、もっと簡単な方法で避けることができます。
詳細は省きますがnyker_gotoさんやまますさんなどのお力を借りて@noglobals
デコレータを使えばいいということで決着します。
簡単な例で説明します。まずは、@noglobals
を定義します。
import builtins
import types
def imports():
for name, val in globals().items():
# module imports
if isinstance(val, types.ModuleType):
yield name, val
# functions / callables
if hasattr(val, '__call__'):
yield name, val
def noglobal(f):
'''
ref: https://gist.github.com/raven38/4e4c3c7a179283c441f575d6e375510c
'''
return types.FunctionType(f.__code__,
dict(imports()),
f.__name__,
f.__defaults__,
f.__closure__
)
準備完了 です!!どう使うかというと、デコレートするだけです。
この手軽さがたまりません。現在、notebookで作業しているのであれば、@noglobals
を関数に片っ端からつけてみてはいかがでしょうか。
簡単ですが、効果の大きいテクニックかなと思います。
最後に、簡単なサンプルのノートブックと、問題を解決しようとした猛者たちの戦いを紹介して終えようと思います。
- sample notebook
- 猛者たちの戦いTweet↓
実はこれ使うとデフォルト引数が使えないっていう問題があるんですが、誰かpythonの言語機能に詳しい人使える方法思いついたりしないですかね。。。。。 https://t.co/6DC7xP5O5b
— まます (@mamas16k) December 6, 2020
以上です!快適なJupyter Notebookライフを送りましょう!