python3x: what would Python print?, local environment versus global environment etc
講義を聞いていたらpop quiz (for nothing unfortunately...)が出てきた。globalとlocalを理解する上で役に立つと思いまとめてみることにする。問題はこちら:
What would Python print?#1
def f():
return 0
def g():
print(f())
def h():
def f():
return 1
g()
h()
My Initial Understanding to it
- globalフレーム内で
func f()
、func g()
、func h()
が定義される。
-
func h()
を呼んだのでfunc h()
の中身に入る。func h()
内のローカル領域でfunc f()
が定義され、func g()
を呼ぶ。
-
pythontutor.comを参考にすると分かりやすいが通常指定された変数を探す場合は今自分のいる
local frame
から上の層(一番上の層がglobal frame)に行く。従ってg()
を呼んでfunc h()
の中のローカルであるdef f(): return 1
をボトムアップで一番新しく定義されたdef f(): return 1
にたどり着き1
を返す。
def f():
return 0
def g():
print(f())
def h():
def f():
return 1
g()
h()
func f()
、func g()
、func h()
が定義される。func h()
を呼んだのでfunc h()
の中身に入る。func h()
内のローカル領域でfunc f()
が定義され、func g()
を呼ぶ。local frame
から上の層(一番上の層がglobal frame)に行く。従ってg()
を呼んでfunc h()
の中のローカルであるdef f(): return 1
をボトムアップで一番新しく定義されたdef f(): return 1
にたどり着き1
を返す。ただこれには大きい誤解があるのではないかと思い始めてきた。
Defining Environments
その前に関数を呼ぶ(新しいenvironmentもしくはフレームを作る)ということはどういうことなのか講義スライドを参考に考えてみる。
一番最後の:
when a user-defined function value is called, the local frame that is created for that call is linked to the defining frame of the function
が最大のヒントだと思う。どこで呼ばれたかというよりはどこで定義されたかのほうが重要なのではないかと。つまり
- globalフレーム内で
func f()
、func g()
、func h()
が定義される。 -
func h()
を呼んだのでfunc h()
の中身に入る。func h()
内のローカル領域でfunc f()
が定義され、func g()
を呼ぶ。 -
呼ばれた関数が作られた領域へと移動する(in this case, func g()'s parent frame is global, in which it was defined)。
func g()
の中に入って行くとprint(f())
があるので(グローバル領域内で)func f()
を探す。 - グローバル領域にある
func f()
はdef f(): return 0
なので0
と表示される。
逆に言えばfunc g()
はfunc h()
のローカルフレームで定義されたdef f(): return 1
にアクセスすることが出来ないのではないかと考えている。理由は単純にfunc g()
を呼んだ時点でグローバル領域にいるので別にfunc h()
を呼んで中に入るか、もしくはfunc g()
をfunc h()
の中にfunc g()
を入れるかしないとアクセス出来ない。
I wonder as I wander
ひとつ目の疑問は上の仮説が正しいのならばもし仮にfunc g()
をfunc h()
内にいれたら違う結果になるのか?
def f():
return 0
def h():
def f():
return 1
def g():
print(f())
g()
h() # 1
恐らくこれは正しいみたい。
2つ目はこれは関数だけに適用することなのか。スライド上ではあえて(それとも深い意味は無いのか?)function valueと言っていたのでそうなのかもしれない??
考えてみたら変数に関しても同じ考え方で良いと思う。一番簡単な考え方は数ある同じ名前を持った変数x
が合ったとして最終的にreturn
もしくはprint
の一番近くにあるものが(もっと適切な言い方をすれば最後にx
として再定義されたもの)がprint
されると考えていいのかもしれない。
What would Python print?#2
続いての問題はこちら:
def f():
return 0
g = f
def f():
return 1
print(g())
個人的にはこっちのほうが簡単だった。単純にfunc f()
が定義されてg
もfunc f()
とリンクされてその後にfunc f()
がもう一つの(下の)func f()
として再アサインされる。よってg
は上のfunc f()
となる。
まさにスライドに書いてあるとおりこれはx=3: y=x: x=4: print(y)
と同じ。ちなみにこれは上で書いた疑問の回答にもなる。
正確な動きを見たい場合はpythontutor.comを。
What would Python print?#3
def f():
return 0
def g():
print(f())
def f():
return 1
g()
def f():
return 0
def g():
print(f())
def f():
return 1
g()
これは上の問題を関数に変えたのと同じ。なので答えは1
となる。
What would Python print?#4
def g(x):
print(x)
def f(f):
f(1)
f(g)
def g(x):
print(x)
def f(f):
f(1)
f(g)
実際にpythontutor.comで見れば動きはわかるが、簡単流れは:
-
g(x)
とf(f)
が定義される。 -
f(g)
で呼ぶ。この時parameterf
をfunc g(x)
として呼んでいるので実際はf(g()) w/ no argument yet
となる。 - 次に
f(1)
を呼んでいるがローカル領域上でf
はg()
にアサインされているので実際はg(1)
を呼んでいるのと同じ。 -
g(1)
を呼びprint(1)
つまりvalueNone
を返してinterpreter上に1
と表示される。
What would Python print?#5
def f():
return 0
def g():
return f()
def h(k):
def f():
return 1
p = k
return p()
print(h(g))
def f():
return 0
def g():
return f()
def h(k):
def f():
return 1
p = k
return p()
print(h(g))
これは上の問題を統合して作ったというイメージ。上の問題ができればこれもすんなり出来るはず。ポイントは関数が呼ばれたら必ずしもローカルフレームから探すわけではないということその関数が定義されたところから探す。ここではg()
はグローバルで定義されているのでh(k)
は見向きもせず上のf()
を見付けて0
を返す。
Assignments don't themselves create new values, but only copy old ones, so that when p is evaluated, it is equal to k, which is equal to g, which is attached to the global environment
What would Python print?#6
def f(p,k):
def g():
print(k)
if k == 0:
f(g,1)
else:
p()
f(None, 0)
def f(p,k):
def g():
print(k)
if k == 0:
f(g,1)
else:
p()
f(None, 0)
これもp()
(=g()
)を呼んだ時にg()
が定義されたところ(=global)に戻ってからk
を探す。つまり答えは0
。
Author And Source
この問題について(python3x: what would Python print?, local environment versus global environment etc), 我々は、より多くの情報をここで見つけました https://qiita.com/weedslayer/items/914308229f58dfb79064著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .