[Python-ml-jp 584] Re: exec 文の使い方
SUZUKI Hisao
suzuki @ acm.org
2001年 9月 13日 (木) 23:11:07 JST
鈴木です
[Python-ml-jp 583] より石本さん
> 対処方法としては、グローバル変数になってしまっても良いのなら
>
> exec id + ' = data' in globals()
>
> のようにするか、もしくはエラーが発生する関数の子関数内では親関数の変数を
> 参照しないようにする、ぐらいだと思います。
ええっと,後者の説明は,ほんの少しだけ不正確です。たとえば,
def foo():
print lambda: x
exec 'a = 10'
print a
でも
SyntaxError: unqualified exec is not allowed in function 'foo' it contains a nested function with free variables
となります。
すなわち,「(関数 foo の入れ子関数 lambda: x には x という自由変数があ
る,つまり) 関数 foo は自由変数のある入れ子関数を持っているわけだから,
(in で名前空間を) 限定していない exec は禁止だ」ということです。
関数にとって自由変数とはその関数の変数のうちで束縛変数 (その関数のロー
カル変数と仮引数) 以外の変数です。だから,エラーになる関数の内部にある
def や lambda の入れ子関数定義からあらゆる自由変数をなくしてしまえば
(たとえばデフォルト引数を利用して束縛変数にしてしまえば) OK です。上の
例では
def foo():
print lambda x=x: x
exec 'a = 10'
print a
ここで気をつけなければいけないのは,関数名はもちろん None とか range
などの組込み名も自由変数(名)だ,ということです。たとえば,lambda: None
もエラーになります。lambda None=None: None としなくてはなりません (…
ヤレヤレ >_<)。
> # exec を使わないのが一番だとは思いますが(^^;
# 100% 賛成
この場合は陽に辞書を使うのが一番だと思います。
--
SUZUKI Hisao >>> def fib(n): return reduce(lambda x, y:
suzuki @ acm.org ... (x,x[0][-1]+x[1]), [()]*n, ((0L,),1L))
Python-ml-jp メーリングリストの案内