Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/maven/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
编译与解释相比,Python具有意外的行为_Python_Python 3.x_Exception_Interpreted Language_Compiled Language - Fatal编程技术网

编译与解释相比,Python具有意外的行为

编译与解释相比,Python具有意外的行为,python,python-3.x,exception,interpreted-language,compiled-language,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语句引发指定的

我得到了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语句引发指定的UnboundLocalError。 根据前面的逻辑,在控件遇到x+=1之前,不应出现此错误。但它确实如此,就像在任何其他编译语言中一样

那么,如何确定代码何时以编译或解释的方式运行

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

它总是按照解释的方式运行;但是,作为第一步,将在整个文件上调用语法检查器,从而生成字节码文件

在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中不可能出现“运行时”语法错误;实现这一点的唯一方法是动态导入带有语法错误的模块

我不确定我是否理解您的问题,但第二种情况下的错误是运行时错误;这就像做int x=0;y=10/x;C;在python中进行语法分析期间,未解析变量作用域“x此时是否存在?”

-

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

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

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

在第二种情况下,编译器看到x在函数中被修改,因此它将x绑定到函数对象。每次调用函数时都会创建函数名称空间,但变量仅在赋值后出现。只有当您执行printx时,python才会意识到您请求的是一个尚未赋值的局部变量。这是一个常见的错误,不是所有的执行路径都像它们应该设置的那样设置了一个变量

稍微修改一下示例,有时设置了局部变量,有时不设置。设置后,可以在局部变量中看到该变量,并且打印工作正常。未设置时,变量不是局部变量,打印失败

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

foo(True)
foo(False)
输出

True before {'val': True, 'x': 1}
1
True after
False before {'val': False}
Traceback (most recent call last):
  File "o.py", line 11, in <module>
    foo(False)
  File "o.py", line 6, in foo
    print(x)
UnboundLocalError: local variable 'x' referenced before assignment

如果您是通过一些简短而非Pythons默认REPL的交互式REPL来运行它,那么您可能会让它在没有错误的情况下实际执行,例如IPythons的qtconsole允许它w/o问题。为什么允许这样做完全取决于REPL及其实现

在Python中,这是一个语法错误;不能为其生成任何字节码:

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
语法特别不允许这样做,只允许字符串文本之间有空格,名称本身不是一个名称,当然是允许的。简而言之,这在解析阶段失败:

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文本以外的任何操作。

好的,在阅读了Doug和Jim的答案后,我想我已经知道了这是如何工作的。 首先,所有示例都在REPL-Ipython中工作,默认为

档案: 如果将其写入文件:

if True:
    print("Hi")
else:
    I am an error. What can you do about it?
并运行该文件,它将抛出一个语法错误。这证明了每当我们从文件执行python代码时,它都会生成字节码,并且由于else中的语句不是有效的python表达式,因此我们会得到一个SyntaxError

答复: 有了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()
轰!一切都崩溃了,在printx语句中会出现UnboundLocalError。这意味着字节码在那里

那么这里到底发生了什么

如果python发现一个变量只出现一次,它会首先读取所有变量来优化其工作。因此,在第二个示例中,当代码遇到printx时,它会尝试查找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,而另一个referencex+=1是问题所在,因此在打印值之前遇到错误。第一个案例在REPL中没有SyntaxError的情况下运行良好,因为它从不费心查看else语句内部,因为它根本不重要。

您能给我看一下代码吗,因为我知道第一个不会导致语法错误。只有当控件到达语句时才会出现错误。“这就是我的问题所在。”阿披舍克贝拉补充道。我很困惑,你怎么能在没有语法错误的情况下运行它。你能提供其他细节吗?什么python版本
你在使用什么平台?好的。。我想我可能已经知道出了什么问题。。当我在实时解释器中编写第一个时,它工作得很好。但是当我在一个文件中编写代码时,语法错误终于出现了。第二种是范围阴影。在全局范围中有一个变量x,但每当它遇到像x+=1这样的编辑时,它只在局部范围中查找x,而所有其他变量都会被删除。因为本地范围中没有变量,所以我们有UnboundLocalError。第一个示例中的else是语法错误。如果你把它放在一个.py文件中并尝试执行它,你会看到。我认为这与你的问题有关,你在解释器外壳中运行代码,即一个REPL。如果我们把它们都放在交互式外壳中。。发生了不一致。。你知道为什么吗?是的,我在用Ipython。但即使我在REPL中同时执行这两个代码。第一个和第二个之间存在差异。我的问题是为什么会出现这种差异。事实上,我无法找到一个独特的理论来解释这两种情况。我也尝试过Python2.7和3.5的默认REPL,结果是一样的。。。为什么这两种说法表现不同?