编译与解释,Python有意想不到的行为

时间:2016-11-27 07:10:01

标签: python python-3.x exception interpreted-language compiled-language

我得到了python执行的意外行为。

if True:
    print("Hello")
else:
    I am an error. what can you do about it?

现在,此代码不会引发SyntaxError,因为控件永远不会进入else语句。在像C ++这样的编译语言中,它会出错。即使在Java中,未使用的代码也是错误的。但不是在Python中。

现在在这种情况下:

x = 10
def foo():
    print(x)
    x += 1

print语句引发指定here的UnboundLocalError。 根据先前的逻辑,该错误不应该在控制遇到x + = 1之前。但它确实像任何其他编译语言一样。

然后如何确定代码何时以编译或解释的方式运行?

修改 如果它被编译成字节码.pyc文件然后解释。那为什么没有检测到第一个例子的else语句?

4 个答案:

答案 0 :(得分:2)

对面。 Python在执行之前将源代码编译为字节代码。第一种情况会在编译阶段引发语法错误。

在第二种情况下,编译器看到函数中修改了add_book :- aggregate_all(count, title(_,_), Count), NewCount is Count + 1, atom_concat('book', NewCount, NewBook). ,因此它将x绑定到函数对象。每次调用函数时都会创建函数名称空间,但只有在分配变量时才会显示该变量。只有当你执行x python意识到你要求一个尚未分配的局部变量时。当并非所有执行路径都设置变量时,这是一个常见错误。

略微修改示例,有时会设置局部变量,有时则不设置。设置后,您会在本地和印刷品中看到变量。未设置时,变量不在本地,并且打印失败。

print(x)

输出

x = 10
def foo(val):
    if val:
        x = 1
    print(val, 'before', locals())
    print(x)
    print(val, 'after')
    x += 1

foo(True)
foo(False)

答案 1 :(得分:1)

它始终按解释运行;但作为第一步,在整个文件上调用语法检查器,生成字节码文件。

在python 2.7和3.5中,你放在顶部的代码会导致语法错误:

python3 junk.py
  File "junk.py", line 4
    I am an error. what can you do about it?
              ^
SyntaxError: invalid syntax

在python中不可能得到'运行时'语法错误;实现这一目标的唯一方法是动态导入语法错误的模块。

我不确定我是否理解了您的问题,但第二种情况中的错误是运行时错误;就像在C中做int x = 0; y = 10/x;一样;变量范围('此时是否存在x?')在python中的语法分析期间未解析。

-

编辑;这是我终端的转储:

Clank:tmp doug$ cat junk.py
if True:
    print("Hello")
else:
    I am an error. what can you do about it?

Clank:tmp doug$ python junk.py
  File "junk.py", line 4
    I am an error. what can you do about it?
       ^
SyntaxError: invalid syntax

Clank:tmp doug$ python3 junk.py
  File "junk.py", line 4
    I am an error. what can you do about it?
       ^
SyntaxError: invalid syntax

答案 2 :(得分:1)

好的,在看完Doug和Jim的答案之后,我想我对这是如何工作有了一个想法。 首先,所有示例都在REPL中工作(Ipython,默认)

<强>文件: 如果你在一个文件中写这个:

if True:
    print("Hi")
else:
    I am an error. What can you do about it?

运行该文件,它将抛出一个SyntaxError。这证明了每当我们从文件执行python代码时,它会生成一个字节码,并且由于else中的语句不是有效的python表达式,我们会得到一个SyntaxError。

<强> REPL : 使用REPL的东西有点依赖。在python解释器中,如果键入

>>>def foo():
       if True:
           print("Hey")
       else:
           I am an error. What can you do about it?
>>>foo()
Hey

成功执行意味着没有字节代码吗?坚持下去。

如果你这样写:

>>>x = 10
>>>def foo():
       print(x)
       x += 1
>>>foo()

轰!一切都崩溃了,你在print(x)语句中得到UnboundLocalError。这意味着字节码就在那里。

那究竟发生了什么?

如果python发现一次变量,它会尝试通过首先读取所有变量来优化其工作。因此,在第二个示例中,当代码遇到print(x)时,它会尝试查找x上的所有操作。很快它找到了声明x + = 1。由于在本地范围内没有提及x,如果没有明确提及,python永远不会在全局范围内查找变量,我们有

UnboundLocalError: local variable 'x' is referenced before assignment 

结论性证据

如果我们写这样的话:

>>>x = 10
>>>def foo():
      if True:
          print(x)
      else:
          x+=1
>>>foo()
UnboundLocalError: local variable 'x' referenced before assignment

那就是它!

x + = 1永远不会被执行但由于print语句打印x而另一个引用(x + = 1)是问题,因此在打印值之前遇到了错误。第一种情况在没有REPL中的SyntaxError的情况下正常工作,因为它从不会在else语句中查找,因为它从不重要。

答案 3 :(得分:0)

如果你通过一些简短的交互式REPL(而不是Pythons默认的REPL)来运行它,你可能会让它实际执行而没有错误(IPython s&#39; qtconsole允许它没有问题例)。为什么允许这样做完全取决于REPL及其实现。

在Python中, SyntaxError;不能为它生成任何字节码:

s ="""
i= 1
if i:
    print("Hello")
else:
    I am an error. what can you do about it?
"""
c = compile(s, '', mode='exec')
  File "<string>", line 6
    I am an error. what can you do about it?
       ^
SyntaxError: invalid syntax

语法特别不允许,只允许字符串文字在它们之间放置空格(which Python later concatenates),名称不是(单个)当然允许使用它自己的名字)。简而言之,这在解析阶段失败了:

from parser import suite
st = suite(s)
  File "<string>", line 6
    I am an error. what can you do about it?
       ^
SyntaxError: invalid syntax

当Python看到两个名称用空格分隔时,它不知道该做什么,空格并不意味着任何操作(str文字除外)。