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() 在列表理解中不起作用。
解决方案
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)
这些在技术上不是“方法”,因为它们不附属于一个类。
另一个问题是推导式有自己的本地范围,就好像你定义了一个生成器函数(一个包含 a 的函数yield
)。from 周围(非本地)范围从未在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()
。
代码应该是人类可以理解的(可读性),否则我们仍然会使用汇编语言。太多的魔法可能会令人困惑。使用 eval/exec 进行字符串元编程是 Python 内置的最强魔法。易于使用,但很难正确使用。当你不需要它时避免它。即使你认为你需要它,你也可能不需要:eval()
被初学者(那些知道它存在的人)过度使用,他们几乎从不需要它。
推荐阅读
- git - 如何将子文件夹的副本复制到 Git 中的单独存储库中?
- ionic-framework - httpClient 的问题我收到此错误
- python - 除非从根目录运行,否则 Python 库不会加载
- kubernetes - 如何为 Confluent Rest-Proxy 配置负载均衡器粘性
- google-maps - 谷歌地图潜在的配额滥用场景
- javascript - 如何为 javascript 对象动态地创建变量名?
- r - 将 R 中的任意函数列表组合成新函数 [元编程]
- c# - 使用存储过程更新动态名称表
- python - 如何在pygame中控制单个子弹
- javascript - 使用 JavaScript 将两个 1D 数组的元素合并为 2D 数组的元素