zoukankan      html  css  js  c++  java
  • Python 语言中 eval 与 exec 的相同点和不同点

    相同点

    在 Python 中,eval 和 exec 都可以用来执行动态生成(dynamically generated)的代码。

    两者在Python 3中的函数声明基本相同,如下所示:

    eval(expression[, globals[, locals]])
    exec(object[, globals[, locals]])

    其中,输入参数中,globals 必须是字典(dict)类型,表示全局空间的变量,若未提供,则通过 globals() 方法获取全局变量,若提供的字典类型对象不包含名为 __builtins__ 的键,则会在表达式解析前,插入这个键,其值设为内置模块 builtins 的引用;而 locals 参数可以是任何可映射类型的对象,表示局部空间的变量,若未提供,则通过 locals() 方法获取局部变量。

    不同点

    下面从关键字类型、第一个输入参数、内调 compile 函数 这 3 个方面,讨论 eval 和 exec 的不同之处。

    1. 类型不同

    eval 在 Python 2 和 Python 3 中都是函数(function);而 exec 在 Python 2 中是语句(statement),在 Python 3 中是函数。

    2. 第一个输入参数不同

    eval 是 evaluate 的英文简写,只能用来计算单独一个 Python 表达式(expression)的值,返回值是这个表达式的执行结果;在 Python 中,表达式(expression)定义为可以在变量赋值中,进行赋值的对象:

    # An expression in Python is whatever you can have as the value in a variable assignment:
    a_variable = (anything you can put within these parentheses is an expression)

    而 exec 是 execute 的英文简写,用来执行 Python 语句(statement),如循环语句、try...except...异常处理语句、class 定义、函数定义等,无返回值,即返回值始终为 None。

    基本示例,如下所示:

    >>> a = 5
    >>> eval('37 + a')   # it is an expression
    42
    >>> exec('37 + a')   # it is an expression statement; value is ignored (None is returned)
    >>> exec('a = 47')   # modify a global variable as a side effect
    >>> a
    47
    >>> eval('a = 47')  # you cannot evaluate a statement
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<string>", line 1
        a = 47
          ^
    SyntaxError: invalid syntax

    3. compile 函数的模式不同

    eval 和 exec 在输入字符串类型时,内部都会首先调用 compile 函数编译为 bytecode,eval 函数对应的模式是 'eval',而 exec 对应的模式是 'exec'。compile 函数用来将输入参数 source 编译为 code 对象,具体声明如下:

    compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1)

    其中,参数 source 通常为包含 Python 源码的字符串;参数 filename 应该给出从中读取代码的文件,或一些可识别的值,常常使用 '<string>' ;参数 mode 指定读取的代码的编译类型:如果包含多个语句,采用 'exec' 模式,如果只包含单一表达式,则采用 'eval' 模式;可选参数 flags 和 dont_inherit 用来控制 future 模块语句影响源码编译;参数 optimize 指定编译器的优化级别。更多内容参见 compile 官方文档

    采用 'exec' 模式的 compile 函数可以编译包含任意数量语句的源码为 bytecode,隐含返回值总是 None;而采用 'eval' 模式的 compile 函数只可以编译单一表达式为 bytecode,并返回这个表达式的值。如果在 'eval' 模式下,compile 函数的输入源码中包含语句或任何超出了单一表达式的要求,则会抛出 SyntaxError 异常。一些具体示例,如下:

    >>> eval(compile('20200926', '<string>', 'exec'))  # code returns None
    >>> eval(compile('20200926', '<string>', 'eval'))  # code returns 20200926
    20200926
    >>> exec(compile('20200926', '<string>', 'eval'))  # code returns 20200926,
    >>>                                          # but ignored by exec
    
    >>> compile('for i in range(3): print(i)', '<string>', 'eval')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<string>", line 1
        for i in range(3): print(i)
          ^
    SyntaxError: invalid syntax

    实际上,eval 只接收单一表达式(eval accepts only a single expression),只是在字符串直接传递给 eval 函数时有效。此时内部会使用 compile(source, '<string>', 'eval') 编译为 bytecode。如果一个包含 bytecode 的 code 对象传递给 exec 或 eval ,它们的表现是相同,除了 exec 总是会返回 None。所以采用 eval 函数执行带有语句的字符串也是可以的,但需要首先使用 compile 函数将源码转为 bytecode,再传给 eval 方法。具体示例,如下:

    >>> eval(compile('if 1: print("Hello")', '<string>', 'exec'))
    Hello
    >>>

    参考资料

    [1] The exec statement in Python 2. https://docs.python.org/2.7/reference/simple_stmts.html#exec

    [2] The exec function in Python 3. https://docs.python.org/3/library/functions.html#exec

    [3] The eval function in Python. https://docs.python.org/3/library/functions.html#eval

    [4] What's the difference between eval, exec, and compile? https://stackoverflow.com/questions/2220699/whats-the-difference-between-eval-exec-and-compile

  • 相关阅读:
    tuple 元组及字典dict
    day 49 css属性补充浮动 属性定位 抽屉作业
    day48 选择器(基本、层级 、属性) css属性
    day47 列表 表单 css初识
    day 46 http和html
    day 45索引
    day 44 练习题讲解 多表查询
    day 40 多表查询 子查询
    day39 表之间的关联关系、 补充 表操作总结 where 、group by、
    day38 数据类型 约束条件
  • 原文地址:https://www.cnblogs.com/klchang/p/13736133.html
Copyright © 2011-2022 走看看