2016-11-14 4 views
5

Почему буквальная оценка 5 * 7 не работает, а 5 + 7 - нет?Почему ast.literal_eval ('5 * 7') терпит неудачу?

import ast 

print(ast.literal_eval('5 + 7')) 
# -> 12 

print(ast.literal_eval('5 * 7')) 
# -> 
Traceback (most recent call last): 
    ... 
ValueError: malformed node or string: <_ast.BinOp object at ...> 

documentation не объясняет это.

Я нашел эту проблему после ответа на этот вопрос на SO: Getting the result of a string.

+7

' аст.literal_eval' менее мощный и, следовательно, менее опасен, чем простой eval. Думаю, это делает его менее двух оценок: :) –

ответ

9

ast.literal_eval() принимает + в проанализированных данных, поскольку 5+2j (комплексное число *) являются действительными литералы. То же самое относится к -. Чтобы код был прост, не делается попытки исключить + или - в качестве двоичных операторов.

Других операторов не допускается; функция предположительно, чтобы принимать литералы, а не выражения.

Другими словами, работы 5 + 7 являются ошибкой, но трудно решить, не нарушая поддержки для построения сложных чисел. implementation ограничивает использование операндов, которые являются числами, унарными + и - или другими бинарными операторами (поэтому вы не можете использовать их для объединения списков или создания разности заданий).

Также см несколько связанных Python записей BugTracker: #25335 ast.literal_eval fails to parse numbers with leading "+", #22525 ast.literal_eval() doesn't do what the documentation says и #4907 ast.literal_eval does not properly handled complex numbers


* Технически говоря, 2j является действительным буквальным; Python анализирует 5+2j как int(5) binop(+) complex(0, 2) и только позже производит объект complex(5, 2) из результата при фактическом выполнении добавления.

+1

'-' также разрешено. –

+0

Спасибо, Марджн, я подозревал что-то вроде этого. Означает ли это, что АСТ является результатом оценки? Надеюсь, это не так. –

+1

@ AnttiHaapala: Да, я ждал моего поезда; связь в лондонских туннелях suxors. –

4

Вопрос не в том, «почему есть * не принимается», а скорее «почему есть + принято вообще».

ast.literal_eval может анализировать литералы, но не выражения. Однако в Python комплексные числа не выражаются как одно буквальное значение; вместо этого они состоят из реальной части и мнимой части, объединенной вместе; мнимая часть сигнализируется j. literal_eval, таким образом, необходимо поддерживать двоичные файлы + и - для поддержки комплексных констант чисел, таких как 1 + 2j или -3.4e-5 - 1.72e9j.

Во многих версиях, включая Python 3.5, literal_eval гораздо более слабым, чем это нужно быть - она ​​принимает любую цепочку сложения и вычитания для тех пор, пока обе левые и правые оценки в любой число, таким образом, (1 + 3) + 2 + (4 - 5) все еще анализируется, даже если он не является сложной константой, состоящей из реальной + мнимой части.


+ и - не принимаются безоговорочно: если вы пытаетесь добавить 2 списков вместе, это не получится, даже если он может разобрать список литералов, а сложение определяется для списков:

>>> ast.literal_eval('[1] + [2]') 
Traceback (most recent call last): 
... 
ValueError: malformed node or string: <_ast.BinOp object at 0x7fdddbe785f8> 
>>> ast.literal_eval('[1, 2]') 
[1, 2] 
>>> [1] + [2] 
[1, 2] 

 Смежные вопросы

  • Нет связанных вопросов^_^