如何与当地人EXEC工作?如何与当地人EXEC工作?(How does exec work with

2019-05-04 21:38发布

我认为这将打印3,但它打印1:

def f():
    a = 1
    exec("a = 3")
    print(a)

Answer 1:

这个问题在一定程度上的讨论Python3的bug列表 。 最终,得到这个行为,你需要做的:

def foo():
    ldict = {}
    exec("a=3",globals(),ldict)
    a = ldict['a']
    print(a)

如果你检查的Python3文档exec ,你会看到下面的注释:

至于功能描述的默认行为当地人locals()修改默认的当地人字典也不应尝试:下面。 传递一个明确的当地人解释,如果你需要看后功能当地人的exec()返回的代码的影响。

回头参考的bug报告的特定消息 ,乔治·布兰德说:

要动态修改函数的本地人也不是没有可能的几个后果: 通常情况下,功能当地人不存储在一个字典,而是一个数组 ,其索引在编译时确定从已知的语言环境。 这与高管加入新的当地人至少碰撞。 老exec语句规避这一点,因为编译器知道,如果没有全局/当地人ARGS一个exec发生在一个功能,该命名空间将是“未优化”,即不使用当地人阵列。 由于EXEC()现在是一个正常的功能, 编译器不知道什么是“执行”可以被绑定到,因此不能治疗是特别

重点是我的。

所以,它的要点是,Python3可以更好地通过不允许默认情况下,这种行为优化使用局部变量。

而对于完整起见,如上面的评论中提到,这样工作按预期在Python 2.X:

Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41) 
[GCC 4.3.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> def f():
...     a = 1
...     exec "a=3"
...     print a
... 
>>> f()
3


Answer 2:

如果你是一个方法里面,你可以这样做:

class Thing():
    def __init__(self):
        exec('self.foo = 2')

x = Thing()
print(x.foo)

你可以在这里读更多关于它的内容



Answer 3:

究其原因,你不能在函数中使用改变局部变量exec以这种方式,为什么exec的行为方式是这样,可以概括为以下几点:

  1. exec是最内部范围中,它被称为的范围内共享其本地范围内的功能。
  2. 当你定义一个函数的范围内,一个新的对象时,它会在其本地命名空间访问,也就是说,它会修改local()的字典。 当你定义一个新的对象exec它的作用大致等同于以下内容:

from copy import copy
class exec_type:
    def __init__(self, *args, **kwargs):
        # default initializations
        # ...
        self.temp = copy(locals())

    def __setitem__(self, key, value):
        if var not in locals():
            set_local(key, value)
        self.temp[key] = value

temp是一个临时的命名空间,每个实例(每次调用的时间之后重置exec )。


  1. Python的开始查找从本地命名空间中的名字。 它被称为LEGB方式。 Python从本地namespce开始然后查找到封闭范围,那么全球,并在最终它会查找BUIT命名空间中的名字。

一个更全面的例子是类似以下内容:

g_var = 5

def test():
    l_var = 10
    print(locals())
    exec("print(locals())")
    exec("g_var = 222")
    exec("l_var = 111")
    exec("print(locals())")

    exec("l_var = 111; print(locals())")

    exec("print(locals())")
    print(locals())
    def inner():
        exec("print(locals())")
        exec("inner_var = 100")
        exec("print(locals())")
        exec("print([i for i in globals() if '__' not in i])")

    print("Inner function: ")
    inner()
    print("-------" * 3)
    return (g_var, l_var)

print(test())
exec("print(g_var)")

输出:

{'l_var': 10}
{'l_var': 10}

当地人都一样。

{'l_var': 10, 'g_var': 222}

加入后g_var和改变l_var它只会增加g_var离开了l_var不变。

{'l_var': 111, 'g_var': 222}

l_var因为我们正在改变,在一个实例(一个调用exec)打印当地人改变。

{'l_var': 10, 'g_var': 222}
{'l_var': 10, 'g_var': 222}

在这两种功能的当地人和高管的本地l_var不变, g_var加入。

Inner function: 
{}
{'inner_var': 100}
{'inner_var': 100}

inner_function的地方是一样Exec的地方。

['g_var', 'test']

全球仅包含g_var (扣除后的特殊方法)和函数的名称。

---------------------

(5, 10)
5


文章来源: How does exec work with locals?