主にプログラミングに関して。Python, .NET Framework(C#), JavaScript, その他いくらか。
記事にあるサンプルやコードは要検証。使用に際しては責任を負いかねます

スポンサーサイト

                
tags:
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Pythonでクロージャ

                
tags:
JavaScriptでクロージャというものを知ったので、Pythonでも。

2つめのスクリプトを書くとき、外側の関数内変数(文字、数字)への代入ができないことを知った。で、リストを使ったらできた…


def outer(name):
def inner0(kingaku):
return name + ", give me " + str(kingaku) + "yen!"
def inner1(kingaku):
return name + ", give you " + str(kingaku) + "yen!"
return [inner0, inner1]

katsuage, mitsugi = outer('John')
print katsuage(10000)
print mitsugi(100)



def outer(kingaku):
kin = [kingaku]
def inner(name):
string = name + ", give me " + str(kin[0]) + "yen!"
print string
kin[0] = kin[0]/10

return inner

katsuage = outer(100000)
katsuage('John')
katsuage('John')
katsuage('John')

>>>
John, give me 100000yen!
John, give me 10000yen!
John, give me 1000yen!


なぜリストならできるのか。なんとなく気になることだ。仮説を立ててみる。変数にリストが入った変数を代入すると、参照渡しとなる(下記参照)。一方で変数に数値や文字列が入った変数を代入すると、コピーされた値が渡される。


>>> x=[3,3]
>>> y=x
>>> y[0]=1
>>> x
[1, 3]
>>> z=1
>>> q=z
>>> q=3
>>> z
1


内部関数が外部関数の変数から値をとってくるとき、”代入”を使っているなら、参照先の変数がリストならポインタを取ってきていることになる。ポインタを取ってきているならそれを参照してメモリに代入をすることは可能だ。

しかし参照先の変数が数値や文字だったらどうだろう。ただコピーされた値を取ってくるだけで、ポインタはない。メモリ上のどこにというあるべきポインタの指定がない。するとどこに代入すればいいかわからない。代入できない。そんなとこなんじゃないだろうか。

ムキになってさらにスクリプトを書いた。クロージャでリストを使わずにできんだろかと。それが下記。

def outer(kingaku):
def inner(name):
try:
eval(kin)
except:
kin = kingaku
string = name + ", give me " + str(kin) + "yen!"
print string
kin = kin/10
return inner

katsuage = outer(100000)
katsuage('John')
katsuage('John')
katsuage('John')

>>>
John, give me 100000yen!
John, give me 100000yen!
John, give me 100000yen!


JavaScriptと明らかに違う。内部関数の中の変数が保持されていない。そういえばDive into Pythonでのクロージャの説明文は”動的な関数の中で外部の引数の値を使うテクニックをクロージャと呼ぶ”と。中の変数を保持するなんてことは書いてないな。Pythonisitaはジェネレータを使うんだな。
            

コメントの投稿

非公開コメント

プロフィール

hMatoba

Author:hMatoba
Github

最新記事
リンク
作ったものなど
月別アーカイブ
カテゴリ
タグリスト

検索フォーム
Amazon
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。