使用 exec 定义变量,在引用它时引发 NameError

Using exec to define a variable, raises an NameError when referencing it

我现在 运行 一个关于变量的错误(首先我已经知道使用 exec 不是最好的选择,但我不想现在进入那个)引用它时未定义。在我添加使用标准时间格式 (1:36) 的能力之前,考虑到它在我使用 exec(f'oneMileMark.append(entry{i}.get())')(此时它已经是一个浮点数)时工作得非常好,我觉得很奇怪。

for i in range(numOfRunners):
    if i%4 == 0: # used to distinguish between a runner's name and different times
        exec(f'time = entry{i}.get()') # gets the value of entry{i} and saves it as time
        minutes,seconds=time.split(':') # splits time into mins and secs
        newTime=float(minutes) + float(seconds)/60 # combines the minutes and hours into one bariable
        oneMileMark.append(newTime) # adds newTime to a list

给出错误:

Traceback (most recent call last):
  File "/Users/Me/Desktop/Computer Programming/Python 3.x/Assignments/Programming 2/8/9_15 Computing 5k Mile Splits/main.py", line 91, in <module>
    app = Application(root)
  File "/Users/Me/Desktop/Computer Programming/Python 3.x/Assignments/Programming 2/8/9_15 Computing 5k Mile Splits/main.py", line 12, in __init__
    self.get_runner_data()
  File "/Users/Me/Desktop/Computer Programming/Python 3.x/Assignments/Programming 2/8/9_15 Computing 5k Mile Splits/main.py", line 53, in get_runner_data
    hours,minutes=time.split(':')
NameError: name 'time' is not defined

基于你的回溯和 , you are using exec 在一个 class 的方法中,像这样:

class Foo:
    def bar(self):
        exec('x = "Hello World"')
        print(x)

exec 在没有 globals 参数的函数定义中执行时,它创建的任何变量都被分配给一个新的临时名称空间,无法访问。本质上,您的 time 变量是在内部范围内创建的(在 exec 完成后被丢弃),因此您无法在该范围之外访问它。

>>> Foo().bar()
Traceback (most recent call last):
  ... 
  File "..\main.py", line 4, in bar
    print(x)
NameError: name 'x' is not defined

为什么你以前的 exec() 以前工作是因为它只访问 oneMileMark 并用 .append() 改变列表,并且没有尝试为变量分配新的东西。

要解决这个问题,您可以使用 eval 而不是 exec,这样您就可以计算表达式,同时保持变量赋值保持在同一范围内:

for i in range(numOfRunners):
    if i%4 == 0:
        time_ = eval(f'entry{i}.get()')
        minutes,seconds=time_.split(':')
        ... 

注意:如果您要在模块级别(在函数或 class 定义之外)使用 exec,则任何变量赋值都将在全局命名空间上起作用:

>>> exec('x = "Hello World"')
>>> x
'Hello World'