30

eval()我在玩耍时偶然发现了 Python中的一个函数。我想不出需要这个函数的情况,除了可能是语法糖。谁能举个例子?

4

14 回答 14

52

eval并且exec是动态获取一些源代码的方便快捷的方式,也许稍微修改一下,然后执行它 - 但它们几乎不是最好的方式,尤其是在生产代码中,而不是“快速和 -肮脏的”原型等。

例如,如果我必须处理这样的动态 Python 源,我会使用ast模块——ast.literal_evaleval(你可以直接在表达式的字符串形式上调用它,如果它是一次性的并且依赖于仅在简单的常量上,或者先做node = ast.parse(source),然后保持node周围,也许用合适的访问者来处理它,例如用于变量查找,然后literal_eval是节点) - 或者,一旦将节点置于适当的形状并针对安全问题对其进行审查,我可以compile它(产生一个代码对象)并从中构建一个新的函数对象。远没有那么简单(除了与最简单的情况ast.literal_eval一样eval简单!),但在生产质量代码中更安全、更可取。

对于我看到人们(ab-)使用execandeval的许多任务,Python 强大的内置函数(例如getattrand setattr、索引到globals()、&c)提供了更可取且实际上通常更简单的解决方案。对于解析 JSON 等特定用途,库模块等json更好(例如,参见 SilentGhost 对耳鸣对这个问题的回答的评论)。等等等等……

于 2009-07-06T15:30:21.320 回答
16

维基百科上的文章内容eval丰富,并详细介绍了各种用途。

它建议的一些用途是:

  • 评估数学表达式
  • 编译器引导
  • 脚本(一般动态语言非常适合这个)
  • 语言导师
于 2009-07-06T14:24:58.430 回答
13

您可能希望使用它来允许用户输入他们自己的“scriptlet”:表达式(甚至是小函数),可用于自定义复杂系统的行为。
在这种情况下,如果您不必太在意安全隐患(例如,您有受过教育的用户群),那么 eval() 可能是一个不错的选择。

于 2009-07-06T14:31:22.930 回答
6

过去,我使用 eval() 向我的应用程序添加调试接口。我创建了一个 telnet 服务,它让你进入正在运行的应用程序的环境中。输入通过 eval() 运行,因此您可以在应用程序中以交互方式运行 Python 命令。

于 2009-07-06T14:29:19.050 回答
5

在我曾经编写的一个程序中,您有一个输入文件,您可以在其中指定几何参数作为值和先前值的 python 表达式,例如:

a=10.0
b=5.0
c=math.log10(a/b)

python 解析器读取此输入文件并使用 eval() 获得评估值和表达式的最终数据。

我不声称它是好的编程,但我不必驱动核反应堆。

于 2009-07-06T14:28:12.887 回答
2

我用它作为一个快速的 JSON 解析器......

r='''
{
    "glossary": {
        "title": "example glossary"
        }
}
'''

print eval(r)['glossary']['title']
于 2009-07-06T15:03:08.057 回答
2

您可以在装饰器中使用 eval:

#this replaces the original printNumber with a lambda-function,
#which takes no arguments and which calls the old function with
#the number 10
@eval("lambda fun: lambda: fun(10)")
def printNumber(i: int) -> None:
    print("The number is %i", i)

#call
printNumber()

虽然您不能使用复杂的表达式,例如

@lambda fun: lambda: fun(10)
def ...

也不

@(lambda fun: lambda: fun(10))
def ...

你不能在那里使用 lambda 表达式,因为装饰器应该是一个标识符:

@myModule.functionWithOneArg

或函数调用:

@functionReturningFunctionWithOneArg(any, "args")

您会看到使用字符串调用函数 eval 在这里有有效的语法,但 lambda 表达式没有。(-> https://docs.python.org/3/reference/compound_stmts.html#function-definitions

于 2017-12-30T15:23:16.000 回答
1

eval()通常不是很有用。我使用它的少数几件事之一(嗯,它exec()实际上是,但它非常相似)是允许用户编写我用 Python 编写的应用程序的脚本。如果它是用 C++ 之类的东西编写的,我将不得不在应用程序中嵌入一个 Python 解释器。

于 2009-07-06T14:27:07.570 回答
1

Eval 是一种在程序中与 Python 解释器交互的方法。您可以将文字传递给 eval 并将其作为 python 表达式进行评估。

例如 -

print eval("__import__('os').getcwd()")

将返回当前工作目录。

干杯

于 2009-07-06T14:33:46.577 回答
1

eval() 用于单个句子,而 exec() 用于多个句子。

通常我们使用它们来添加或访问一些脚本,就像 bash shell 一样。

因为他们可以在内存中运行一些字节脚本,如果你有一些重要的数据或脚本,你可以解码和解压缩你的“秘密”,然后做你想做的一切。

于 2014-05-13T08:42:40.277 回答
1

我刚刚遇到了一个很好的 eval 用法。我正在为一些代码编写一个测试套件,并创建了一个测试类,其中每个方法都是要运行的测试。我想要一种方法,这样我就可以运行所有的测试方法,而不必单独调用每个方法。所以,我写了一些相当肮脏的东西。

class Test:
    def __init__(self, *args):
       #bs

    def test1(self):
       #bs

    def test2(self):
       #bs

if __name__ == "__main__":
    import argparse
    #argparse bs
    test = Test(*bs_args)
    for func in (i for i in dir(test) if i[0] != '_' and i not in test.__dict__):
        print(eval('test.{func}()'.format(func = func)))

任意测试用例的动态评估非常酷。我只需要编写方法,保存后我可以将方法包含在我的测试套件中。至于代码,我基本上只是检查测试对象中定义的方法,并确保它们不是默认的python“魔术”方法或测试对象的属性。之后我可以假设它们是方法并且可以被评估。

于 2017-01-02T05:36:22.540 回答
0

我用它向主程序输入变量值:

test.py var1=2 var2=真

...

var1=0
var2=False
for arg in sys.argv[1:]:
    exec(arg)

在主程序中允许关键字 args 的粗略方法。如果有更好的方法告诉我!

于 2014-02-24T18:22:29.850 回答
0

我有一个案例,我将 eval 与 informix 数据库结合使用。由于某种原因,查询返回了一个像这样形成的字符串

query_result = "['1', '2', '3']"

我只是在查询结果上使用了 eval,所以 python 将它解释为一个字符串列表。

[int(i) for i in eval(query_result)]
> [1,2,3]

我无法更改数据库,因此这是获取整数的一种快速(且肮脏)的方法。

于 2020-08-31T14:32:18.453 回答
-1

我用来exec在 Python 中创建一个插件系统。

    尝试:
        exec ("from " + plugin_name + "import Plugin")
        myplugin = 插件(模块选项,配置 = 配置)
    除了 ImportError,消息:
        致命的(“没有这样的模块” + plugin_name + \
               " (或没有插件构造函数) 在我的 Python 路径中:" + str(message))
    除了例外:
        致命(“模块”+插件名称+“无法加载:”+\
               str(sys.exc_type) + ":" + str(sys.exc_value) + \
               ".\n 可能是一个缺失或错误的选项?")

使用如下插件:

类插件:

    def __init__ (自我):
        经过

    def 查询(自我,arg):
         ...

你可以这样称呼它:

    结果 = myplugin.query("something")

我认为没有exec/就不能在 Python 中使用插件eval

于 2009-07-06T15:39:25.597 回答