使用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
根据您的回溯信息和上一篇文章,您是在类似这样的类的方法中使用 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屋!