使用exec定义变量,在引用它时引发NameError [英] Using exec to define a variable, raises an NameError when referencing it

查看:210
本文介绍了使用exec定义变量,在引用它时引发NameError的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

解决方案

根据您的回溯信息和上一篇文章,您是在类似这样的类的方法中使用 exec :

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

在不带globals参数的函数定义中执行exec时,其创建的任何变量将分配给新的临时名称空间,该名称空间无法访问.本质上,您的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'

I'm now running an error (first off I already know that using exec isn't the best option but I'd rather not get into that right now) about a variable being undefined when referencing it. Which I find very strange considering it was working perfectly fine when I was using exec(f'oneMileMark.append(entry{i}.get())') (it was already a float at this point) before I added the ability to use the standard time format (1:36).

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

Which gives the error:

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

解决方案

Based on your traceback and previous post, you are using exec within a method of a class like so:

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

When exec is executed within a function definition without a parameter for globals, any variables it creates is assigned to a new, temporary namespace, which cannot be accessed. Essentially, your time variable was made in an inner scope (which gets thrown away after exec finishes), and so you cannot access it outside of that scope.

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

Why your previous exec() used to work before is because it only accessed oneMileMark and mutated the list with .append(), and didn't try to assign something new to the variable.

To solve this, you can use eval instead of exec so you can evaluate the expression while keeping your variable assignment remaining in the same scope:

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

Note: If you were to use exec in the module level (outside of function or class definitions), any variable assignments will work on the global namespace:

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

这篇关于使用exec定义变量,在引用它时引发NameError的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆