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

2024-12-12 08:40:00
admin
原创
175
摘要:问题描述:如何在 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大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1579  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1355  
  信创产品在政府采购中的占比分析随着信息技术的飞速发展以及国家对信息安全重视程度的不断提高,信创产业应运而生并迅速崛起。信创,即信息技术应用创新,旨在实现信息技术领域的自主可控,减少对国外技术的依赖,保障国家信息安全。政府采购作为推动信创产业发展的重要力量,其对信创产品的采购占比情况备受关注。这不仅关系到信创产业的发展前...
信创和国产化的区别   8  
  信创,即信息技术应用创新产业,旨在实现信息技术领域的自主可控,摆脱对国外技术的依赖。近年来,国货国用信创发展势头迅猛,在诸多领域取得了显著成果。这一发展趋势对科技创新产生了深远的推动作用,不仅提升了我国在信息技术领域的自主创新能力,还为经济社会的数字化转型提供了坚实支撑。信创推动核心技术突破信创产业的发展促使企业和科研...
信创工作   9  
  信创技术,即信息技术应用创新产业,旨在实现信息技术领域的自主可控与安全可靠。近年来,信创技术发展迅猛,对中小企业产生了深远的影响,带来了诸多不可忽视的价值。在数字化转型的浪潮中,中小企业面临着激烈的市场竞争和复杂多变的环境,信创技术的出现为它们提供了新的发展机遇和支撑。信创技术对中小企业的影响技术架构变革信创技术促使中...
信创国产化   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

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

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

内置subversion和git源码管理

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

免费试用