列表理解中的评估函数给出名称错误
Eval function in list comprehension gives name error
def print_formatted(number):
for n in range(number):
n+=1
methods = ['int', 'oct', 'hex', 'bin']
ls = [eval(method + '(n)') for method in methods]
我不知道为什么 eval() 在列表理解中不起作用。
您的部分代码完全没问题。
methods = ['int', 'oct', 'hex', 'bin']
ls = [eval(method + '(n)') for method in methods]
应该按预期工作。
我不知道您为什么会收到名称错误。如果您能提供完整的跟踪记录,那将是最好的,这样我们就可以帮助您进行调试。
我看到的唯一错误是您的 for 循环中有 n+=1
。您不需要增加 n
因为 for n in range(number):
已经增加了它。
它确实有效,但是 eval 不理解 '(n)'
(n 未解析)。尝试如下:
number = 5
def print_formatted(number):
numberlst = []
for n in range(number):
# n+=1 <-- not needed
methods = ['int', 'oct', 'hex', 'bin']
ls = [eval(method + '('+ str(n) + ')') for method in methods]
numberlst.append(ls) # <-- add list for each value of n
return numberlst
for lst in print_formatted(number):
print(lst)
输出:
[0, '0o0', '0x0', '0b0']
[1, '0o1', '0x1', '0b1']
[2, '0o2', '0x2', '0b10']
[3, '0o3', '0x3', '0b11']
[4, '0o4', '0x4', '0b100']
eval()
在这里有点矫枉过正。这些内置函数本身就是对象。无需遍历字符串。
不需要在每个循环中将 1 添加到 n
,因为您可以从 1 开始范围,然后再结束 1。
而且您实际上并没有打印或返回列表。你可以做一个 print(ls)
什么的。
def print_formatted(number):
for n in range(1, number+1):
methods = [int, oct, hex, bin]
ls = [method(n) for method in methods]
print(ls)
这些在技术上不是“方法”,因为它们没有附加到 class。
另一个问题是推导有自己的局部作用域,就好像你定义了一个生成器函数(一个包含 yield
的函数)。来自周围(非本地)范围的 n
从未在理解中使用过,因此编译器未将其包含在理解的本地中,因此 eval()
看不到它。不过,您可以显式传入您想要 eval()
的命名空间。
def print_formatted(number):
for n in range(number):
n+=1
methods = ['int', 'oct', 'hex', 'bin']
loc = locals() # gets local namespace outside of comp as a dict
ls = [eval(method + '(n)', loc) for method in methods]
print(ls)
print_formatted(4)
[1, '0o1', '0x1', '0b1']
[2, '0o2', '0x2', '0b10']
[3, '0o3', '0x3', '0b11']
[4, '0o4', '0x4', '0b100']
您也可以在理解中的某个地方使用 n
,以便编译器将其包含在理解的局部变量中。 (eval()
默认使用本地命名空间,当你不提供时。)在 eval()
字符串中包含 n
是不够的,因为它可能在运行时发生变化,即在编译器必须决定理解的局部变量的时间。
def print_formatted(number):
for n in range(number):
n+=1
methods = ['int', 'oct', 'hex', 'bin']
ls = [eval(method + '(n)') for method in methods for _ in [n]]
print(ls)
我不建议你真的这样做。以上只是为了解释这里发生了什么,以防你使用一个最小的例子来说明一个确实需要 eval()
的案例的问题,但你在这里根本不需要 eval()
。
代码应该是人类可以理解的(可读性很重要),否则我们仍然会使用汇编语言。太多的魔法会让人困惑。 eval/exec 的字符串元编程是 Python 中最强大的魔法。易于使用,但很难正确使用。当你不需要它时避免它。即使你认为你需要它,你也可能不需要:eval()
被初学者(那些知道它存在的人)过度使用,他们几乎不需要它。
def print_formatted(number):
for n in range(number):
n+=1
methods = ['int', 'oct', 'hex', 'bin']
ls = [eval(method + '(n)') for method in methods]
我不知道为什么 eval() 在列表理解中不起作用。
您的部分代码完全没问题。
methods = ['int', 'oct', 'hex', 'bin']
ls = [eval(method + '(n)') for method in methods]
应该按预期工作。
我不知道您为什么会收到名称错误。如果您能提供完整的跟踪记录,那将是最好的,这样我们就可以帮助您进行调试。
我看到的唯一错误是您的 for 循环中有 n+=1
。您不需要增加 n
因为 for n in range(number):
已经增加了它。
它确实有效,但是 eval 不理解 '(n)'
(n 未解析)。尝试如下:
number = 5
def print_formatted(number):
numberlst = []
for n in range(number):
# n+=1 <-- not needed
methods = ['int', 'oct', 'hex', 'bin']
ls = [eval(method + '('+ str(n) + ')') for method in methods]
numberlst.append(ls) # <-- add list for each value of n
return numberlst
for lst in print_formatted(number):
print(lst)
输出:
[0, '0o0', '0x0', '0b0']
[1, '0o1', '0x1', '0b1']
[2, '0o2', '0x2', '0b10']
[3, '0o3', '0x3', '0b11']
[4, '0o4', '0x4', '0b100']
eval()
在这里有点矫枉过正。这些内置函数本身就是对象。无需遍历字符串。
不需要在每个循环中将 1 添加到 n
,因为您可以从 1 开始范围,然后再结束 1。
而且您实际上并没有打印或返回列表。你可以做一个 print(ls)
什么的。
def print_formatted(number):
for n in range(1, number+1):
methods = [int, oct, hex, bin]
ls = [method(n) for method in methods]
print(ls)
这些在技术上不是“方法”,因为它们没有附加到 class。
另一个问题是推导有自己的局部作用域,就好像你定义了一个生成器函数(一个包含 yield
的函数)。来自周围(非本地)范围的 n
从未在理解中使用过,因此编译器未将其包含在理解的本地中,因此 eval()
看不到它。不过,您可以显式传入您想要 eval()
的命名空间。
def print_formatted(number):
for n in range(number):
n+=1
methods = ['int', 'oct', 'hex', 'bin']
loc = locals() # gets local namespace outside of comp as a dict
ls = [eval(method + '(n)', loc) for method in methods]
print(ls)
print_formatted(4)
[1, '0o1', '0x1', '0b1']
[2, '0o2', '0x2', '0b10']
[3, '0o3', '0x3', '0b11']
[4, '0o4', '0x4', '0b100']
您也可以在理解中的某个地方使用 n
,以便编译器将其包含在理解的局部变量中。 (eval()
默认使用本地命名空间,当你不提供时。)在 eval()
字符串中包含 n
是不够的,因为它可能在运行时发生变化,即在编译器必须决定理解的局部变量的时间。
def print_formatted(number):
for n in range(number):
n+=1
methods = ['int', 'oct', 'hex', 'bin']
ls = [eval(method + '(n)') for method in methods for _ in [n]]
print(ls)
我不建议你真的这样做。以上只是为了解释这里发生了什么,以防你使用一个最小的例子来说明一个确实需要 eval()
的案例的问题,但你在这里根本不需要 eval()
。
代码应该是人类可以理解的(可读性很重要),否则我们仍然会使用汇编语言。太多的魔法会让人困惑。 eval/exec 的字符串元编程是 Python 中最强大的魔法。易于使用,但很难正确使用。当你不需要它时避免它。即使你认为你需要它,你也可能不需要:eval()
被初学者(那些知道它存在的人)过度使用,他们几乎不需要它。