exec如何与当地人合作?

ube*_*kel 24 python exec locals python-3.x

我以为这会打印3,但它打印1:

def f():
    a = 1
    exec("a = 3")
    print(a)
Run Code Online (Sandbox Code Playgroud)

Mar*_*off 41

Python3错误列表对此问题进行了一些讨论.最终,要获得此行为,您需要执行以下操作:

def foo():
    ldict = {}
    exec("a=3",globals(),ldict)
    a = ldict['a']
    print(a)
Run Code Online (Sandbox Code Playgroud)

如果您查看Python3文档exec,您将看到以下注释:

默认的locals如locals()下面的函数所述:不应尝试修改默认的locals字典.如果您需要在函数exec()返回后查看代码对locals的影响,则传递显式的locals字典.

回到关于错误报告的特定消息,Georg Brandl说:

如果没有几个结果,则无法动态修改函数的局部函数:通常,函数局部函数不存储在字典中,而是存储在数组中,其索引在编译时从已知语言环境确定.这至少与exec添加的新本地人发生冲突.旧的exec语句规避了这一点,因为编译器知道如果函数中没有发生全局/局部因子的exec,那么该命名空间将"未经优化",即不使用本地数组.由于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
Run Code Online (Sandbox Code Playgroud)

  • @AnatolyAlekseev:它已记录在案(从“不支持对默认局部变量的修改”的意义上来说),并且没有好的修复方案不涉及将“exec”恢复为关键字的状态,代码中的性能回归不涉及“不需要这个功能,或者执行非常糟糕的事情来使对局部变量的写入传递到“真正的”局部变量(这在非 CPython 解释器中可能不实用)。要点是,“exec”始终是一个坏主意,在极少数情况下,您“需要”来实现所描述的功能,有一些解决方法(如本答案中所述)。 (3认同)
  • 我明白了,这是 locals() 的问题,它在 python 2.X 中被从 exec 中破解了。这个问题没有像我希望的那样清晰记录。Exec/locals 从 2.X 更改为 3.X 应该在 http://docs.python.org/3.1/library/functions.html#exec 的某个地方指出,我认为 exec 应该有一个方便的参数来规避这种优化。 .. (2认同)
  • 令人难以置信的是,Python 核心开发人员近 10 年来没有采取任何优雅的方式解决这个问题。我可以确认,在 2019 年 8 月的 Python 版本 3.7.2 中,这种不期望/意外的行为仍然存在。 (2认同)

Mac*_*eus 5

如果您在方法内部,您可以这样做:

# python 2 or 3
class Thing():
    def __init__(self):
        exec('self.foo = 2')
    
x = Thing()
print(x.foo)
Run Code Online (Sandbox Code Playgroud)

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