从根本上说,我不认为我们都在思考正确的路线。这里没有最后一行。解释器在完全接收到表达式时引发异常。根据 Python 语法:http://docs.python.org/reference/grammar.html,在您点击右大括号 ')' 之前,表达式并不完整。 Joran Beasley 在 cmets 中针对问题本身给出了相同的简要解释。
你可以做 3 件事来判断它的正确性,而不需要深入研究语法:-
-
在python解释器中编写这段代码:
a=(1+2+0/0+4+5)
这也会引发 ZeroDivionError。
-
在python解释器中编写这段代码:
a=(1+2+0/0+4+5 # 然后按回车
这会给你无效的语法,因为表达式不完整并且不能被解释器解析
PS:这个和问题中提到的代码是一样的
- 在python解释器中编写这段代码:
a = (1
+2
+0/0
+4
+5)
最终,直到您点击右大括号,表达式才会完成。因此,您可以继续在其中添加更多子表达式而不会出现任何异常。因此,从根本上说,解释器并不将这一切都视为行号。它一直等到所有表达式(包括子表达式)都完成。而且,它是一个适合interpeter的编程控制流程。
PS:请原谅我的答案格式。
新编辑:-
@Hayden:我认为通过不深入研究语法很容易解释其中的微妙之处。但是,供您参考,我只是从 URL 中复制代码:http://nedbatchelder.com/blog/200804/the_structure_of_pyc_files.html
运行步骤:-
1. 将问题中询问的代码写入 temp.py 文件并保存,然后将 temp 导入另一个文件或解释器中。这将创建 temp.pyc
2. 现在,将上述 URL 中的完整代码复制并粘贴到 byteCodeDetails.py 中,然后在命令提示符下运行该文件:
python byteCodeDetails.py temp.pyc。函数 show_file 将在此处调用,并给出以下输出:-
magic 03f30d0a
moddate 458c2e50(2012 年 8 月 17 日星期五 23:54:05)代码
argcount 0
nlocals 0 stacksize 3 flags 0040 代码
640600640200640200151764030017640400175a000064050053 5
0
LOAD_CONST 6 (3)
3 LOAD_CONST 2 (0)
6 LOAD_CONST 2 (0)
9 BINARY_DIVIDE
10 BINARY_ADD
11 LOAD_CONST 3 (4)
14 BINARY_ADD
15 LOAD_CONST 4 (5)
18 BINARY_ADD
19 STORE_NAME 0 (a)
22 LOAD_CONST 5(无)
25 RETURN_VALUE
常量
1
2
0
4
5
无
3
名称 ('a',)
varnames ()
freevars ()
cellvars ()
文件名 'C:\Users\Python\temp1.py'
名称 ''
firstlineno 5
lnotab
所以,你可以注意到:-
- 引用上述链接:
在反汇编输出中,最左边的数字 (1, 2, 3) 是原始源文件中的行号,接下来的数字 (0, 3, 6, 9, ...) 是字节偏移量 同样,对于您的代码,最左边的数字只有 5,即行号,右边的列表示由编译器翻译的助记符(由解释器读取)您的代码。,从而指示表达式是如何形成的,并且它们的形成被编译代码中的行号的值所取代。
-
firstlineno 指向 5。
现在,只需对 temp.py 文件中的初始代码稍作更改即可:-
a = (1
+2
+0/0
+4+
5)
现在,再次执行上述 2 个步骤。以下是输出:-
魔法 03f30d0a
moddate 0f8e2e50(2012 年 8 月 18 日星期六 00:01:43)
代码
argcount 0
nlocals 0
stacksize 3
标志 0040
代码
640600640200640200151764030017640400175a000064050053
4
0 LOAD_CONST 6 (3)
3 LOAD_CONST 2 (0)
6 LOAD_CONST 2 (0)
9 BINARY_DIVIDE
10 BINARY_ADD
11 LOAD_CONST 3 (4)
14 BINARY_ADD
5 15 LOAD_CONST 4 (5)
18 BINARY_ADD
19 STORE_NAME 0 (a)
22 LOAD_CONST 5(无)
25 RETURN_VALUE
常量
1
2
0
4
5
无
3
名称 ('a',)
varnames ()
freevars ()
cellvars ()
文件名
'C:\Users\Python\temp1.py'
名称 ''
firstlineno 4
lnotab 0f01
嗯,现在你可以清楚地看到两件事:-
- 字节码由下一行所示的两行组成,分别为'code 640600640200640200151764030017640400175a000064050053',前缀为'4'和'5'。这表明编译器已经解析了 .py 文件并将 temp.py 中的代码转换为 2 行代码,这些代码将由解释器运行。 注意这里第4行的内容无论表达式是否完整都会被解释器执行
-
firstlineno 的值从 5 变为 4
这个冗长讨论的重点是,无论字节码向解释器表明这是一行的开始以及应该为此行执行的相应语句,解释器只运行该行和相应的旁边写着声明。
您问题中的代码将 firstlineno 显示为 5,这就是您在第 5 行收到错误的原因。希望这对现在有所帮助。