pythonのレキシカルスコープのテスト
pythonは、「静的スコープ」らしい。ざっくりと覚えておくべきこと。
- 変数は、
- 関数のローカル環境
- 定義時(実行時では無いというのがポイント)の環境
- グローバル環境、の順番に探される。
- さらに、グローバル環境は、ファイル毎に独立している。
テストをしてみた。実行方法 : func.py, do.pyを同じ所に保存して、do.pyをシェルスクリプトとして実行。
func.py
x = 1 def getFunc1(): x = "a" def func(): print x ##getFunc1の中のxが出力される return func def getFunc2(): def func(): print x ##グローバル環境のxが出力される return func func1 = getFunc1() func2 = getFunc2() print "call of func1 : ", func1() print "call of func2 : ", func2() x = 100 print "call of func1 : ", func1() ##グローバル環境のxを書き換えても影響無し print "call of func2 : ", func2() ##グローバル環境のxを書き換えたので出力が変化 def callFunc2(): x = "in callFunc2" print "call of func2 from inside of function : ", getFunc2()() ##実行時では無く定義時の環境からxを探すので、"in callFunc2"は出て来ないよ callFunc2() def getFunc3(): def func(): print y return func
do.py
#!/usr/bin/env python import func y = 1 func3 = func.getFunc3() try: func3() ##グローバル環境はファイル毎に独立しているので、yが見つからないというエラーが出る except NameError, e: print "calling func3 raises an error : ", e print "call of func1 from do.py : ", func.func1() print "call of func2 from do.py : ", func.func2() func.x = "x" ##別のモジュールに属している変数を上書きすることも可能 print "call of func1 from do.py : ", func.func1() print "call of func2 from do.py : ", func.func2() ##funcモジュールのグローバル環境のxが変更されたので、出力も変化
こうしてみると、静的スコープは殆どオブジェクト指向でないか、と思ってしまう。殆どオブジェクト指向なのは別に構わないんだけど、じゃぁオブジェクト指向との違いは何なのヨ、とか、わざわざクラスを定義出来るのは何故?とか思ってしまうんだけど、まぁカプセル化の単位がファイルだけというのも不便だ。それ以外にも違いはあるんだろうか?と思ったら、ウィキペディアのクロージャの項に
またオブジェクトのインスタンス変数とは、オブジェクトのインスタンスではなく関数の呼び出しに束縛されているという点で異なる。
http://ja.wikipedia.org/wiki/%E3%82%AF%E3%83%AD%E3%83%BC%E3%82%B8%E3%83%A3
とか書いてあった。が、いまいちよく意味が分からんな。