【问题标题】:Using exec to define a variable, raises an NameError when referencing it使用 exec 定义变量,引用它时引发 NameError
【发布时间】:2020-09-22 03:31:14
【问题描述】:

我现在遇到了一个错误(首先我已经知道使用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

【问题讨论】:

    标签: python exec


    【解决方案1】:

    根据您的回溯和previous post,您在类的方法中使用exec,如下所示:

    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(':')
            ... 
    

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

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

    【讨论】:

      猜你喜欢
      • 2021-01-04
      • 1970-01-01
      • 2018-02-10
      • 1970-01-01
      • 2018-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-14
      相关资源
      最近更新 更多