1. exec 不是表达式: python 2. x, 中的一个语句和 python 3. x. 中的一个函数它编译并立即计算一个字符串中包含的语句或者语句集。 例如:

    exec('print(5)') # prints 5.
    # exec 'print 5' if you use Python 2.x, nor the exec neither the print is a function there
    exec('print(5)\nprint(6)') # prints 5{newline}6.
    exec('if True: print(6)') # prints 6.
    exec('5') # does nothing and returns nothing.
  2. eval 是内置函数( 不是语句),它计算表达式并返回表达式生成的值。 例如:

    x = eval('5') # x <- 5
    x = eval('%d + 6' % x) # x <- 11
    x = eval('abs(%d)' % -100) # x <- 100
    x = eval('x = 5') # INVALID; assignment is not an expression.
    x = eval('if 1: x = 4') # INVALID; if is a statement, not an expression.
  3. compile 是 exec 和 eval的低级版本。 它不执行或者评估你的语句或者表达式,但返回可以执行它的代码对象。 模式如下:

    1. compile(string,'','eval') 返回将要执行的代码对象,如果你完成了 eval(string) 。 请注意,在这里模式下,只有用你不能使用语句( 单) 表达式是否有效。
    2. compile(string,'','exec') 返回将要执行的代码对象,如果你完成了 exec(string) 。 你可以在这里使用任意数量的语句。
    3. compile(string,'','single') 类似于 exec 模式,但它将忽略除第一个语句之外的所有内容。 注意,带有结果的if/else 语句被认为是单个语句。

exec用于语句,但不返回任何内容。 eval用于表达式并返回表达式值。

表达式表示"something"而语句表示"做点什么"。

简短答案或者 TL ;DR

eval 和 exec 有 2个差异:

  1. eval 返回被求值的字节码返回的值。

    exec 忽略返回值并总是返回 None ( 在 python 2中,它是一个语句,不能用作表达式,所以它实际上不返回任何内容) 。

    因此:

    >>> eval('42')
    42
    >>> exec('42')
    >>>
  2. 如果包含的code 对象被传递给 exec 或者 eval,它们的行为就会相同,除了返回值( eval 返回返回的值,exec返回 None ) 。

    如果一个包含源代码的字符串被传递给 exec/eval,它在内部编译为使用 compile(source, '<string>', mode) 其中 mode 分别为 exec 或者 eval 。 这就是不同之处所在。

中的compile 'exec' 模式集成任意数量的语句做成一字节码可以隐式地总是返回 None,然而在 'eval' 模式下,它只编译一个表达式转换为字节码可以返回出表达式的值。

>>> eval(compile('42', '<string>', 'exec')) # code return None
>>> eval(compile('42', '<string>', 'eval')) # code returns 42
42
>>> exec(compile('42', '<string>', 'eval')) # code returns 42,
>>> # but ignored by exec

在 'eval' 模式( 如果传入字符串,则使用 eval 函数) 中,如果源代码包含语句或者其他表达式以外的任何内容,compile 将引发异常:

>>> eval('for i in range(3): print(i)')
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

答案越长,a.k.a的细节就越多

exec 和 eval

exec 函数( 在 python 2, 哪个是一个语句) 用于执行动态创建的语句或者程序:

>>> program = 'for i in range(3):\n print("Python is cool")'
>>> exec(program)
Python is cool
Python is cool
Python is cool
>>>

eval 函数对单个表达式执行相同的操作。。和返回表达式的值:

>>> a = 2
>>> my_calculation = '42 * a'
>>> result = eval(my_calculation)
>>> result
84

同时 exec 和 eval 接受要运行的程序/表达式可以指定作为 strunicode 或者 bytes 对象,包含源代码,或者作为 code 对象,其中载有 python 字节码。

如果一个包含源代码的 str/unicode/bytes 被传递给 exec,它的行为等同于:

exec(compile(source, '<string>', 'exec'))

eval 同样的行为等同于:

eval(compile(source, '<string>', 'eval'))

由于所有表达式都可以用作 python ( 这些转换称为 Expr python 中的节点抽象语法 ;反过来就不成立) 中的语句,如果不需要返回值,则可以使用 exec 。 也就是说,你可以使用 eval('my_func(42)') 或者 exec('my_func(42)'),不同之处在于 eval 返回 my_func 返回的值,exec 丢弃它:

>>> def my_func(arg):
... print("Called with %d" % arg)
... return arg * 2
...
>>> exec('my_func(42)')
Called with 42
>>> eval('my_func(42)')
Called with 42
84
>>>

在 2中,只有 exec 接受包含语句的源代码,如 defforwhileimport 或者 class,赋值语句( a.k.a a = 42 ) 或者整个程序:

>>> exec('for i in range(3): print(i)')
0
1
2
>>> eval('for i in range(3): print(i)')
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

exec 和 eval 接受 2个额外的位置参数- globals 和 locals - 它们是代码所看到的全局和局部变量作用域。 这些默认到名为 exec 或者 eval的作用域内的globals()和 locals(),但是任何字典都可以用于 globals 和 locals ( 当然包括 dict )的任何 mapping 。 这些不仅可以用来限制/修改代码所看到的变量,还可以用于捕获 exec 代码创建的变量:

>>> g = {}
>>> l = {}
>>> exec('global a; a, b = 123, 42', g, l)
>>> g['a']
123
>>> l
{'b': 42}

( 如果你显示整个 g的值,则会更长,因为 exec 和 eval 将built-ins模块作为 __builtins__ 添加到全局,如果它丢失的话) 。

在 python 2中,exec 语句的正式语法实际上是 exec code in globals, locals ,如中所示

>>> exec 'global a; a, b = 123, 42' in g, l

但是替代语法 exec(code, globals, locals) 总是被接受过( 见下文) 。

compile

compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1) 内置可以用于加速重复一些相同的代码会事先与 exec 或者通过将源代码编译成一个 code eval 对象的调用。 mode 参数控制 compile 函数接受的代码Fragment类型以及它生成的字节码类型。 选择是 'eval''exec' 和 'single':

  • 'eval' 需要一个单独的表达式,并且会产生字节码,当运行时会返回表达式的值
  • 'exec' 接受从单个表达式到整个代码模块的任何类型的python 构造,并将它们作为模块top-level语句执行
  • 'single' 是一种有限形式的'exec' 包含一个单 语句它能接受一个源代码;如果是表达式语句,它的repr 是 print 艾德到标准 output() 。!

    一个 if - elif - else 链,一个带有 else的循环,和 tryelse 和 finally 块的被认为是一个单一语句。

    一个源 Fragment,包含 2 top-level语句是错误对于 'single',除在 python 2有一个 Bug 死亡,它允许多个顶级中的语句代码,只有第一个会被编译的,其余的将被忽略:

    在 python 2.7.8中:

    >>> exec(compile('a = 5\na = 6', '<string>', 'single'))
    >>> a
    5

    在 python 3.4.2中:

    >>> exec(compile('a = 5\na = 6', '<string>', 'single'))
    Traceback (most recent call last):
    File"<stdin>", line 1, in <module>
    File"<string>", line 1
    a = 5
    ^
    SyntaxError: multiple statements found while compiling a single statement

    这对于制作交互式 python 外壳非常有用。 但是,表达式的值是,即使你 eval的结果代码不正确。

因此 exec 和 eval的最大区别实际上来自于 compile 函数及其模式。


python,只关心calls,除了编译源代码到字节码,compile 支持编制 抽象语法树 ( python 代码的解析树) 成 code 物件,并且在 ast.parse 被写入源代码编译成抽象语法树(compile(source, filename, mode, PyCF_ONLY_AST) 这些代码用于动态地修改源代码,也用于动态代码创建,因为在复杂情况下将代码作为节点的树而不是文本行更容易处理。


而 eval 仅允许你计算一个字符串包含单个表达式,可以 eval 完整的语句,甚至是一个整体模块,它已经与 python compile d 成字节码,也就是说,2,print 是一个命题,并不能直接被 eval 发光二极管:

>>> eval('for i in range(3): print("Python is cool")')
Traceback (most recent call last):
File"<stdin>", line 1, in <module>
File"<string>", line 1
for i in range(3): print("Python is cool")
^
SyntaxError: invalid syntax

它与 'exec' 模式成一个 code 对象并且可以 compile eval 他,这样 eval 函数将返回 None 。

>>> code = compile('for i in range(3): print("Python is cool")',
'foo.py', 'exec')
>>> eval(code)
Python is cool
Python is cool
Python is cool

如果有一个看起来成 eval 和 exec 源代码在 CPython 3,这是非常严重;它们都调用具有相同的参数,唯一的区别就是 PyEval_EvalCode exec 显式返回 None 。

语法桥的exec 差异 python 2和 python 3

python 开销2的一个主要差异是 exec 是一个语句,eval 是内置函数( 两个都是 python 3中内置的函数) 。 exec 在 python 2中的正式语法是众所周知的事实 exec code [in globals[, locals]]

不像大部分的python 2 -to-3 移植 指南 似乎 来建议 CPython中,则 exec 语句 2可以也与语法,该语法使用看起来 到底与候车室的exec 函数调用 python 3 。 原因是 python 0.9.9有 exec(code, globals, locals) 内置函数 ! ,而且内置函数被换成 exec 语句之前的某个位置 python 1.0释放 。

在 1993, 因为是可取途径不破坏向后兼容性与 python 0.9.9,一个 guidovanrossum添加了一个兼容 如果 code 是长度为 2或者 3的元组,并且 globals 和 locals 没有传递到 exec 语句,那么 code 将被解释为该元组的2和 3个元素分别是 globals 和 locals 。 兼容性 hack 未提到即使在 python 1.4文档( 最早可用的在线版本) ;以及因此之前是不知道的许多作家的作品,移植指南和工具,它是 2012年11月 中文档化再次 :

第一个表达式也可以是长度为 2或者 3的元组。 在这种情况下,必须省略可选的部分。 表单 exec(expr, globals) 等效于 exec expr in globals ,而表单 exec(expr, globals, locals) 等同于 exec expr in globals, locals exec的元组形式提供与 python 3的兼容性,其中 exec 是一个函数而不是语句。

对,就是 CPython 2.7,它是可以方便简单的被称为作为一个为 ( 为什么会让人困惑,因为有一个向后兼容的选项) forward-compatibility选项,当它实际上要在那儿为二十年 backward-compatibility 。

因此,exec 是 python 1和 python 2中的一个语句,以及 python 3和 python 0.9.9中的内置函数,

>>> exec("print(a)", globals(), {'a': 42})
42

在每个广泛发行的python 版本中都有相同的行为;并且在 Jython 2.5.2,PyPy 2.3.1 ( python 2.7.6 ) 和 2.6.1过( 他们对CPython的未记录在案行为的赞扬) 。

转载:https://ask.helplib.com/161578

eval 与 exec, compile区别的更多相关文章

  1. eval与exec的区别,以及变量的作用范围

    # eval与exec的区别:eval 有返回值,而 exec没有返回值 # 这两个函数都是执行python语句,注意:里面传的是字符串的格式 a = eval('1+2') a # 这里a有值 3 ...

  2. python3的eval和exec的区别与联系

    eval: 可以把字符串里的字符转换为可执行代码,但只支持一行字符.可以返回执行后得到的值.如下: f = "3+6+9+8"s = eval(f)print(s)输出: &quo ...

  3. Python中eval与exec用法的区别

    Python中eval,exec这两个函数有着相似的输入参数类型和执行功能,因此在用法上经常出现混淆,以至经常用错,程序易抛出错误.下面主要通过这两个函数的语法来阐述区别,并用例子来进一步说明. 首先 ...

  4. 内置函数——eval、exec、compile

    内置函数——eval.exec.compile eval() 将字符串类型的代码执行并返回结果 print(eval('1+2+3+4')) exec()将自字符串类型的代码执行 print(exec ...

  5. 内置函数— — eval、exec、compile

    字符串类型代码:eval.exec.compile eval()  执⾏字符串类型的代码,并返回最终结果 print(eval("2+2")) # 4 n=8 def func() ...

  6. Python中的eval()、exec()及其相关函数

    刚好前些天有人提到eval()与exec()这两个函数,所以就翻了下Python的文档.这里就来简单说一下这两个函数以及与它们相关的几个函数,如globals().locals()和compile() ...

  7. 深度辨析 Python 的 eval() 与 exec()

    Python 提供了很多内置的工具函数(Built-in Functions),在最新的 Python 3 官方文档中,它列出了 69 个. 大部分函数是我们经常使用的,例如 print().open ...

  8. [转]Python中的eval()、exec()及其相关函数

    Python中的eval().exec()及其相关函数   刚好前些天有人提到eval()与exec()这两个函数,所以就翻了下Python的文档.这里就来简单说一下这两个函数以及与它们相关的几个函数 ...

  9. 【转】Python中的eval()、exec()及其相关函数

    [转]Python中的eval().exec()及其相关函数 刚好前些天有人提到eval()与exec()这两个函数,所以就翻了下Python的文档.这里就来简单说一下这两个函数以及与它们相关的几个函 ...

随机推荐

  1. C++模板的理解与使用

    最近发现原来学的东西根本都不理解,所以本人正在恶补C++,把自己对C++中概念的最简单粗暴的理解写下来. 有问题的地方还请指出~随时更正 模板:顾名思义,就是为了方便以后使用而出现的东西,生活中的模板 ...

  2. 使用Python终结“你是什么垃圾”的灵魂拷问!

    目录 0 引言 1 环境 2 需求分析 3 代码实现 4 后记 0 引言 纸巾再湿也是干垃圾?瓜子皮再干也是湿垃圾??最近大家都被垃圾分类折磨的不行,傻傻的你是否拎得清?

  3. System.arraycopy 和 Arrays.copyOf

    System.arraycopy /* native关键字 本地方法 System类 java.lang.System.class 参数说明: src - 源数组. srcPos - 源数组中的起始位 ...

  4. 中转Webshell 绕过安全狗(二)

    前言 在实践中转webshell绕过安全狗(一)中,在服务端和客户端均为php.某大佬提示并分享资源后,打算使用python完成中转.部分代码无耻copy. 客户端 本地127.0.0.1,安装pyt ...

  5. 点菜网---Java开源生鲜电商平台-商品基础业务架构设计-商品分类(源码可下载)

    点菜网---Java开源生鲜电商平台-商品基础业务架构设计-商品分类 (源码可下载) 说明:我们搞过电商的人都可以体会到,搞生鲜电商是最复杂的,为什么复杂呢?我总结了有以下几个业务特性决定的: 1. ...

  6. JavaScript 事件(捕获和冒泡 兼容性写法)

    事件    浏览器客户端上客户触发的行为都称为事件 所有的事件都是天生自带的 不需要人为绑定 只需要我们去触发通过obj.事件名=function(){} 我们给元素的事件绑定了一个方法 事件名:on ...

  7. 2018.11.2 2018NOIP冲刺之最短公共父串

    很有意思的一个题 试题描述 给定字符串A和字符串B,要求找一个最短的字符串,使得字符串A和B均是它的子序列. 输入 输入包含两行,每行一个字符串,分别表示字符串A和字符串B.(串的长度不超过30) 输 ...

  8. 终于有人说清楚了--XGBoost算法

    1. 什么是XGBoost XGBoost是陈天奇等人开发的一个开源机器学习项目,高效地实现了GBDT算法并进行了算法和工程上的许多改进,被广泛应用在Kaggle竞赛及其他许多机器学习竞赛中并取得了不 ...

  9. scrapy基础知识之 pycharm 调试小技巧:

    在项目根目录下新建main.py文件,用于调试 from scrapy.cmdline import executeexecute(["scrapy","crawl&qu ...

  10. redis可视化客户端

    1. 场景描述 redis安装完成后,使用命令行看还是有点不方便,github上有开源的redis可视化客户端,很好用,介绍下. 2.解决方案 使用redisclient客户端,来操作redis. 2 ...