[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 メーリングリストの案内