注意: この質問は Python 2.7.3 を前提としています。
関数のローカル名前空間を動的に変更するための適切なアプローチを探しています。できれば、ボディ関数に最小限の混乱を追加する方法で。
私が考えていることは、次のようになります。
import os
from namespace_updater import update_locals
def somefunc(x, y, z):
# ...
# ...
# this and that
# ...
# ...
if os.environ.get('FROBNICATE'):
from frobnitz import frobnicate
update_locals(frobnicate(locals()))
#
# life goes on, possibly with duly frobnicated local variables...
# ...
# ...
# ...
ありがとう!
PS: 以下は、機能しないアプローチです。
これに対する最も素朴なアプローチは、次のようなものです。
locals().update(new_locals(locals())
...しかし、ドキュメントではlocals()
、そのようなブードゥーに依存してローカル変数を変更することに対して非常に明示的に警告しているため、これを回答として送信しないでください (ドキュメントの警告を無視する優れたケースを作成できない限り)。
ナイーブスケールの次は次のようなものです
for k, v in new_locals(locals()).items():
exec ('%s = v' % k)
AFAICT、そのようなコードは「邪魔にならない」ことはできません(つまり、関数の本体にある必要があります)。これは理想的ではありません。しかし、本当の解決策は、exec ('%s = v' % k)
ハッキングがいくつかの奇妙なバグにつながる可能性があるということです.
私が「奇妙なバグ」と書くとき、私が意味するのは「私のように理解力が乏しい人には奇妙に見えるバグexec ('%s = v' % k)
」です。このハックについての私の理解はどれほど薄いですか? これに答えるには、以下のスクリプトを検討してください。これには 3 つのバリエーションがあります。(1) 示されているとおり。#
(2) 18 行目の先頭を削除した後。(3) 15 行目と 18 行目の両方の最初の行を削除した後#
(つまり、この亜種では、コードはコメントアウトされていません)。このスクリプトのバリアント (2) と (3) の動作は予測できませんでした。バリアント (1) の動作を 50% 以上の信頼度で予測することさえできませんでした。それは、私の理解がどれほど薄いかです。exec ('%s = v' % k)
ハック。このスクリプトの 3 つの亜種が (python 2.7 の下で) どのように動作するかを自信を持って正しく予測できない限り、状況の把握は私のものと同じくらい希薄であると言っても過言ではありませexec ('%s = v' % k)
ん。
x = 'global x' # 01
y = 'global y' # 02
def main(): # 03
x = 'local x' # 04
y = 'local y' # 05
run(locals()) # 06
print 'OK' # 07
return 0 # 08
# 09
def run(namespace): # 10
global y # 11
print locals().keys() # 12
for k, v in namespace.items(): # 13
print '%s <- %r' % (k, v) # 14
exec ('%s = v' % k) #in locals() # 15
print locals().keys() # 16
x = x # 17
#z = lambda: k # 18
print x # 19
print y # 20
# 21
exit(main()) # 22