列表解析中的评估函数给出名称错误

时间:2020-07-20 15:01:36

标签: python list-comprehension nameerror

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()为什么不能用于列表理解。

3 个答案:

答案 0 :(得分:1)

它确实可以工作,但是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']

答案 1 :(得分:1)

eval()在这里过大。这些内建函数本身就是对象。不需要遍历字符串。

不需要在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)

从技术上讲,它们不是“方法”,因为它们没有附加到类上。


另一个问题是,理解具有自己的局部范围,就好像您定义了生成器函数(包含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()默认不使用本地名称空间。)在n字符串中包含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 for _ in [n]]
        print(ls)

我不建议您实际执行此操作。上面只是为了说明这里发生的情况,以防您使用一个最小的示例来说明确实需要eval()但您根本不需要eval()的情况下的问题。< / p>

代码对于人类来说应该是可理解的(可读性计数),否则我们都仍将使用汇编语言。太多的魔法可能会造成混乱。使用eval / exec进行字符串元编程是Python内置的最强大的功能。易于使用,但难以正确使用。不需要时避免使用它。即使您认为自己需要它,也可能不会:eval()被(知道它存在的那些)初学者过度使用,他们几乎从不需要。

答案 2 :(得分:0)

您的部分代码完全没问题。

methods = ['int', 'oct', 'hex', 'bin']
ls = [eval(method + '(n)') for method in methods]

应该按预期工作。

我不知道为什么会出现名称错误。最好是给我们完整的跟踪记录,以便我们可以帮助您进行调试。

我看到的唯一错误是for循环中有n+=1。您不需要增加n,因为for n in range(number):已经增加了。