Ответ 1
В принципе, я не думаю, что все мы думаем о правильных строках. Здесь нет такой вещи, как последняя строка. Исключение возникает интерпретатором, когда он получает выражение полностью. Согласно грамматике Python: http://docs.python.org/reference/grammar.html, выражение не будет полностью заполнено, пока вы не нажмете закрывающую фигуру ")". Краткое объяснение тому же было дано Джораном Бисли в комментариях к самому вопросу.
Вы можете сделать 3 вещи, чтобы судить о правильности этого, не углубляясь глубоко в грамматику: -
-
Введите этот код в интерпретаторе python:
а = (1 + 2 + 0/0 + 4 + 5)
Это также вызывает ZeroDivionError.
-
Введите этот код в интерпретаторе python:
a = (1 + 2 + 0/0 + 4 + 5 # И нажмите enter
Это дает неверный синтаксис, поскольку выражение не является полным и не может быть проанализировано интерпретатором PS: Это то же самое, что и код, упомянутый в вопросе
- Введите этот код в интерпретаторе python:
a = (1
+2
+0/0
+4
+5)
В конце концов, выражение не будет завершено, пока вы не нажмете на закрывающую фигуру. Следовательно, вы можете продолжать добавлять в него дополнительные подвыражения, не получая никаких исключений. Таким образом, в основном интерпретатор не видит все это как номера строк; он ждет, пока все выражения (включая подвыражения) не будут завершены. И, это правильный поток управления программированием для интерпретатора.
PS: Прошу форматировать ответ.
Новое редактирование: -
@Хайден: Я думал, что будет легко объяснить тонкости, не углубляясь слишком глубоко в грамматику. Но для вашей справки я просто копирую код из 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 и будет выдавать следующий результат: -
магия 03f30d0a
moddate 458c2e50 (пт авг. 17 23:54:05 2012) код
argcount 0
nlocals 0 stacksize 3 flags 0040 code
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
consts
1
2
0
4
5
None
3
имена ('a',)
varnames()
freevars()
cellvars()
filename '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)
Теперь запустите еще два шага. Ниже приведен вывод: -
магия 03f30d0a
moddate 0f8e2e50 (сб авг 18 00:01:43 2012)
код
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_ADD5 15 LOAD_CONST 4 (5)
18 BINARY_ADD
19 STORE_NAME 0 (a)
22 LOAD_CONST 5 (Нет)
25 RETURN_VALUE
consts
1
2
0
4
5
None
3
names ('a',)
varnames()
freevars()
cellvars()
filename 'C:\Users\Python\temp1.py'
имя ''
firstlineno 4
lnotab 0f01
Хорошо, теперь вы можете ясно видеть 2 вещи: -
- Байт-код состоит из двух строк, показанных в следующей строке, на "код 640600640200640200151764030017640400175a000064050053" с префиксом "4" и "5". Это показывает, что компилятор проанализировал файл .py и преобразовал код в temp.py в 2 строки кода, которые будут выполняться интерпретатором. Обратите внимание, что содержимое строки 4 будет выполняться интерпретатором независимо от того, будет ли это выражение завершено или нет
- Значение firstlineno изменяется на 4 вместо 5
Вся эта длительная дискуссия состоит в том, что везде, где байт-код указывает интерпретатору, что это то, где начинается строка, и соответствующие операторы, которые должны выполняться для этой строки, тогда интерпретатор просто запускает эту строку и соответствующий написанные рядом с ним.
Код в вашем вопросе показывает firstlineno как 5, поэтому вы получаете сообщение об ошибке в строке 5. Надеюсь, это поможет сейчас.