动态设置局部变量[重复]

2024-12-12 08:40:00
admin
原创
172
摘要:问题描述:如何在 Python 中动态设置局部变量(变量名是动态的)?解决方案 1:与已经发布的其他答案相反,您不能locals()直接修改并期望它能够起作用。>>> def foo(): lcl = locals() lcl['xyz'] = 42 print(xy...

问题描述:

如何在 Python 中动态设置局部变量(变量名是动态的)?


解决方案 1:

与已经发布的其他答案相反,您不能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()

在 Python 的 C 实现中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()

解决方案 2:

其他人建议将 赋值给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()(并冒着覆盖函数实际需要的变量的风险)呢?

解决方案 3:

(这只是给其他谷歌用户的一个简短说明)

好吧,修改locals() 不是解决问题的办法(虽然修改globals() 应该可行)。与此同时,exec 可能是,但它的速度太慢了,所以,与正则表达式一样,我们可能compile()首先要这样做:

# var0 = 0; var1 = 1; var2 = 2
code_text = '
'.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

解决方案 4:

直接修改就可以了locals()

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

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

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

解决方案 5:

我猜,我花了……几个小时试图解决缺少函数闭包的问题,​​然后我想出了这个,它可能会有所帮助:

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()

...

这是一个相当笨拙/做作的例子,但如果有很多本地变量或您仍在进行原型设计,这种模式就会变得有用。大多数情况下,我只是对复制或移动所有数据存储以处理回调委托等感到苦恼。

解决方案 6:

您可以使用本地字典,将所有动态绑定作为条目放入字典中。然后,知道此类“动态变量”的名称后,您就可以使用该名称作为键来获取其值。

解决方案 7:

假设我们有以下词典:

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']}

一句话:

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
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用