动态设置局部变量

你如何在Python中动态设置局部变量?

(变量名称是动态的)

更新:我知道这不是好的做法,言论是合法的,但这并不是一个坏的问题,只是一个更理论的 – 我不明白为什么这证明downvotes。

与已发布的其他答案相反,您不能直接修改locals()并期望它能正常工作。

 >>> def foo(): lcl = locals() lcl['xyz'] = 42 print(xyz) >>> foo() Traceback (most recent call last): File "<pyshell#6>", line 1, in <module> foo() File "<pyshell#5>", line 4, in foo print(xyz) NameError: global name 'xyz' is not defined 

修改locals()是未定义的。 当locals()globals()是相同的函数之外它将工作; 里面的功能通常是不行的。

使用字典,或在对象上设置属性:

 d = {} d['xyz'] = 42 print(d['xyz']) 

或者如果你愿意,可以使用一个类:

 class C: pass obj = C() setattr(obj, 'xyz', 42) print(obj.xyz) 

编辑 :访问不是函数(所以模块,类定义,实例)的名称空间中的变量通常通过字典查找来完成(正如Sven在注释中指出的那样存在异常,例如定义__slots__类)。 函数locals可以针对速度进行优化,因为编译器(通常)事先知道所有的名字,所以在调用locals()之前,没有字典。

在Python实现中,本地变量locals() (从函数内调用)创建一个从当前变量初始化的普通字典。 在每个函数中,任何对locals()的调用都会返回相同的字典,但是对locals()每个调用都会使用局部变量的当前值进行更新。 这可以给人的印象是字典中的元素赋值被忽略(我原来写的是这种情况)。 因此,从locals()返回的字典中对现有键的修改只能持续到对同一作用域中locals()的下一次调用。

在IronPython中,工作有点不同。 任何调用其中的locals()函数都会为其局部变量使用一个字典,所以对局部变量的赋值会改变字典并赋值给字典,改变变量但是 ,只有在显式调用该名字的locals()下。 如果在IronPython中将不同的名称绑定到locals函数,那么调用它将为您提供名称被绑定的作用域的局部变量,并且无法通过它访问函数局部变量:

 >>> def foo(): ... abc = 123 ... lcl = zzz() ... lcl['abc'] = 456 ... deF = 789 ... print(abc) ... print(zzz()) ... print(lcl) ... >>> zzz =locals >>> foo() 123 {'__doc__': None, '__builtins__': <module '__builtin__' (built-in)>, 'zzz': <built-in function locals>, 'foo': <function foo at 0x000000000000002B>, '__name__': '__main__', 'abc': 456} {'__doc__': None, '__builtins__': <module '__builtin__' (built-in)>, 'zzz': <built-in function locals>, 'foo': <function foo at 0x000000000000002B>, '__name__': '__main__', 'abc': 456} >>> 

这一切都可以在任何时候改变。 唯一保证的是你不能依赖于分配给locals()返回的字典的结果。

其他人建议分配给locals() 。 这在函数内部不起作用,在这个函数中,使用LOAD_FAST操作码访问本地, 除非你在函数中有一个exec语句。 为了支持这个语句,它可以创建在编译时不知道的新变量,Python将被强制在函数中通过名字访问局部变量,所以写入locals()可行的。 exec可以在执行的代码路径之外。

 def func(varname): locals()[varname] = 42 return answer # only works if we passed in "answer" for varname exec "" # never executed func("answer") >>> 42 

注意:这只适用于Python 2.x. 他们在Python 3中取消了这种愚蠢的行为,而其他的实现(Jython,IronPython等)也可能不支持它。

虽然这是一个坏主意。 如果你不知道他们的名字,你将如何访问变量? locals()[xxx]大概。 那么为什么不使用自己的字典而不是污染locals() (并且有机会覆盖你的函数实际需要的变量)?

我花了最后几个小时,我想,试图破解功能关闭的缺乏,我想出了这个,这可能会有所帮助:

 common_data = ...stuff... def process(record): ...logic... def op(): for fing in op.func_dict: # Key line number 1 exec(fing + " = op.func_dict[fing]") # Key line number 2 while common_data.still_recieving: with common_data._lock: if common_data.record_available: process(common_data.oldest_record) time.sleep(1.0) op.func_dict.update(locals()) # Key line number 3 threading.Thread(target = op).start() ... 

这是一个相当笨手笨脚的例子,但是如果有很多本地人或者你还在进行原型设计,这个模式就变得有用了。 大多数情况下,我只是为了处理回调委托等而对所有正在复制或移动的数据存储区感到苦恼。

您可以使用本地字典,并将所有动态绑定作为项目放入字典中。 然后知道这样的“动态变量”的名称,您可以使用该名称作为密钥来获得其价值。

(只是别人googlin快速笔记)

好的,所以修改locals() 不是要走的路 (当修改globals() 应该工作 )。 与此同时, exec 可能是 ,但是速度很慢,所以和正则表达式一样,我们可能首先compile()它:

 # var0 = 0; var1 = 1; var2 = 2 code_text = '\n'.join( "var%d = %d" % (n, n) for n in xrange(3) ) filename = '' code_chunk = compile( code_text, filename, 'exec' ) # now later we can use exec: exec code_chunk # executes in the current context 

你可以直接修改locals()

 locals()['foo'] = 'bar' 

但更好的方法是有一些字典,将所有动态变量名称保存为字典键:

 d = {} for some in thing: d[some] = 'whatever' 

比方说,我们有下面的字典:

 DictionaryA = {'No Rating': ['Hobbit', 'Movie C', 'Movie G'], 'Forget It': ['Avenger', 'Movie B'], 'Must See': ['Children of Men', 'Skyfall', 'Movie F'], '3': ['X-Men', 'Movie D'], '2': ['Captain America', 'Movie E'], '4': ['Transformers', 'Movie A']} 

我想创建新的字典,如下所示:

 NewDictionary1 = {'No Rating': ['Hobbit', 'Movie C', 'Movie G']} NewDictionary2 = {'Forget It': ['Avenger', 'Movie B']} NewDictionary3 = {'Must See': ['Children of Men', 'Skyfall', 'Movie F']} 

一个oneliner:

 dics = [{k:v} for k,v in DictionaryA.iteritems()] 

将被输出到:

 [{'Must See': ['Children of Men', 'Skyfall', 'Movie F']}, {'Forget It': ['Avenger', 'Movie B']}, {'No Rating': ['Hobbit', 'Movie C', 'Movie G']}, {'3': ['X-Men', 'Movie D']}, {'2': ['Captain America', 'Movie E']}, {'4': ['Transformers', 'Movie A']}] 

但要精确地声明我们可以使用的变量:

 >>> i=0 >>> lcl = locals() >>> for key,val in DictionaryA.iteritems(): lcl["Dict" + str(i)] = {key:val} i += 1 

可以看出前3个Dict变量:

 >>> Dict0 {'Must See': ['Children of Men', 'Skyfall', 'Movie F']} >>> Dict1 {'Forget It': ['Avenger', 'Movie B']} >>> Dict2 {'No Rating': ['Hobbit', 'Movie C', 'Movie G']} 

正如其他人所说,如果你想把它放在一个函数中,你应该把它添加到globals()

 >>> glb = globals() >>> for key,val in DictionaryA.iteritems(): glb["Dict" + str(i)] = {key:val} i += 1