如何动态修改函数的本地命名空间?
注意:这个问题假定
Python 2.7.3.
我正在寻找一种理智的方法来动态修改函数的本地命名空间,最好是以一种给body函数添加最少杂乱的方式. 我的想法会是这样的: 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()) …但是documentation for 接下来在天真的规模就像是 for k,v in new_locals(locals()).items(): exec ('%s = v' % k) AFAICT,这样的代码不能“不在路上”(即它必须在函数体内),这是不理想的.但真正的交易破坏者是exec(‘%s = v’%k)黑客攻击会导致一些奇怪的错误. 当我写出“奇怪的错误”时,我的意思是“对于那些对我来说很难掌握的人(‘%s = v’%k)看起来很奇怪的错误”.我对这个黑客的把握有多么脆弱?要回答这个问题,请考虑以下脚本.它有三种变体:(1)完全如图所示; (2)删除第18行的前导号码后; (3)删除第15行和第18行中的第一个#(即对于此变体,没有注释掉代码).我无法预测此脚本的变体(2)和(3)的行为.我甚至无法预测变体(1)的行为超过50%.这是我对exec(‘%s = v’%k)黑客的掌握程度.除非你能够自信而正确地预测这个脚本的三个变体将如何表现(在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 解决方法
我将介绍我认为接近合理的唯一方法,然后我会试着说服你不要使用它.
def process(**kw): mycode = """ print 'Value of foo is %s' % (foo,) print 'Value of bar is %s' % (bar,) """ exec mycode in kw vars = {'foo': 2,'bar': 3} process(**vars) 使用这种方法,您至少可以获得代码注入攻击的一些保护.显式指定包含代码“局部变量”的字典,因此您可以完全控制运行exec语句时变量空间的内容.您不必破解函数对象或其他类似物的内部. 我知道decorator module在执行@decorator时使用exec来操作动态创建函数中的参数名称,并且可能还有其他常用模块使用它.但我只有一种情况是,exec明显胜过Python中的替代品,而且还有一种用于评估. 我在你的问题中没有看到这种情况.除非上面的mycode需要做一些非常时髦的事情,比如创建一个以kw给出的参数名称的函数,你很可能只是简单地编写代码,并且可能在紧要关头使用locals(). def process(**kw): print 'Value of foo is %s' % (kw['foo'],) print 'Value of bar is %s' % (kw['bar'],) process(foo=2,bar=3) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |