Pythonには「ビルトイン」というスコープもあることを知ったので、学んだことをまとめておきたいと思います。
ビルトインスコープとは
筆者みたいにPython未経験で他言語の経験がある場合、ローカルスコープとグローバルスコープはピンとくる方も多いと思うのですが、これとは別に「ビルトインスコープ」というものがあります。
名前からするとグローバルが一番広い(外側)ように思えてくるのですが、そうではなくてビルトインが一番広いというのは個人的にはハマりポイントかなと思います。
このビルトインスコープですが、具体的にどんなスコープなのかと言うと「複数のファイルをまたがったスコープ」となります。
実際に簡単なプログラムを書いて確認していきたいと思います。
以下は、main.py
でfooモジュールをインポートして、show_score 関数を参照しているコードになります。
score = 100 # グローバル
def show_score():
print('score: ', score)
import foo
foo.show_score()
python main.py
score: 100
main モジュールを少し書き換えてみます。
score は foo モジュールでのグローバル変数なので、main モジュールから参照する場合は、foo モジュールを経由する形になります。
import foo
print(foo.score)
python main.py
100
さらに、main モジュールを少し書き換えてみます。
すると、scoreは定義されていません
エラーが発生しました。
score は foo モジュールでの変数であり、main モジュールの変数ではないため、エラーになっているようです。
import foo
print(score) # fooモジュールのscore変数を参照したつもり
python main.py
Traceback (most recent call last):
File "main.py", line 3, in <module>
print(score)
NameError: name 'score' is not defined
グローバルという言葉の印象からするとprint(score)
で参照したいところですが、エラーになってしまいます。
builtins モジュール
上記のエラーを回避する方法として、score を「ビルトインスコープに登録する」があります。
グローバルからビルトインにスコープを広げて、他モジュールから直接参照できるようにするイメージです。
ビルトインスコープへの登録は、builtins
モジュールを利用すれば実現できます。
import foo
print(score) # 「foo.」なしにscoreを参照できる
import builtins
builtins.score = 100
def show_score():
print('score: ', score)
python main.py
100
builtins モジュールをインポートし、score をビルトインスコープに登録しています。
上記のエラーがなくなったことを確認できるかと思います。
ただし、何でもかんでもビルトインスコープに登録してしまうと、かなり危険なコードになってしまうためくれぐれもお気を付けください。
ちなみに、上記コードにも登場した print 関数ですが、これはビルトインスコープに存在しています。
そのため、モジュール名.print()
みたいに書く必要がないのですね。
補足
本記事ではビルトインスコープに注力したかったため触れていませんが、実は他にも「エンクロージングスコープ」というスコープもあるようで、興味のある方は調べてみてください。