locals & globals()

关于locals()和globals()的记录

locals()陷阱

可以简单理解为locals()只读,globals()可读可写,因此操作locals()生成动态变量不可行,但是操作globals()生成动态变量可行,且globals()全局共用

def test():
    globals()['a'] = 1
    locals()['b'] = 2


test()
print(a)
print(b)
--------------------------------------
1
Traceback (most recent call last):
  File "C:/Users/wayne/Desktop/StereoConstruction/testlocalglobal.py", line 12, in <module>
    print(b)
NameError: name 'b' is not defined

exec作用域问题

def exec(cmd, globals=None, locals=None):
	......

exec函数原型如上,

当不传递globals和locals时,exec会继承上文的locals和globals

当只传递globals时,exec会给globals自动添加__builtin__等内置内容并复制一份给locals

当globals和locals都传递时,exec会给两者都加上__builtin__等内置内容

具体的可以写点简单的代码验证

exec执行会改变下文的globals和locals,如下,

expr = """
y = 20
z = 30
print(locals())
print(globals())
"""


def func():
    exec(expr)


x = 10

print(locals())
exec(expr)
# func()
print(globals())
print(locals())

print(y)
------------------------------
20

此处可行因为在exec中会改变globals()的值从而可以拿到新的变量

但是如果把exec放在一个函数里执行则不行,因为其改变不了globals(),如下

expr = """
y = 20
z = 30
print(locals())
print(globals())
"""


def func():
    exec(expr)


x = 10

print(locals())
# exec(expr)
func()
print(globals())
print(locals())

print(y)
--------------------------------------------
Traceback (most recent call last):
  File "C:/Users/wayne/Desktop/StereoConstruction/testlocalglobal.py", line 25, in <module>
    print(y)
NameError: name 'y' is not defined

那如果在exec中改变globals应该就可以拿到新变量了吧,如下,

expr = """
globals()['y'] = 20
"""

def func():
    exec(expr)

x = 10
func()

print(y)
---------------------------------
20

可以看到确实如预料的那样

给exec传递参数

考虑如下需求场景,需要在exec函数中生成一个变量并且在下文被使用

  • 方案一

方案一就可以采用在exec中修改globals将后续要用的变量变成global变量,但是这样做的缺点也是显而易见的,增加了一个全局变量,并且由于IDE无法识别这种语法导致有红色波浪线强迫症无法接受,那么还可以怎么做呢,这个时候就可以利用exec的参数传递功能了

  • 方案二

利用exec的参数传递功能,先来看一个错误解决方案

expr = """
a = 10
"""

def func():
    a = None
    exec(expr)
    print(a)

func()
---------------------------------------
None

可以看到并没有完成想要的功能,为什么呢,继续分析

expr = """
print(1, locals())
a = 10
b = 20
print(2, locals())
"""

def func():
    a = None
    exec(expr)
    print(3, locals())
    print(a)

func()
--------------------------------
1 {'a': None}
2 {'a': 10, 'b': 20}
3 {'a': None, 'b': 20}
None

可以看到,由于locals()的只读特性,我们无法改变原有key='a’的值,但是可以新增key=‘b’,虽然由于只读性质这个b依旧不能被当作一个变量使用

上一篇:HDP 10.Azkaban 编译及 LDAP 配置


下一篇:arm-linux-gnueabihf-g++: error trying to exec 'cc1plus': execvp: No such file or directory