python eval abstract-syntax-tree

python - ¿Por qué falla ast.literal_eval(''5*7'')?



abstract-syntax-tree (2)

La pregunta no es "por qué * no se acepta" sino más bien "por qué se acepta + en absoluto".

ast.literal_eval puede analizar literales, pero no expresiones. Sin embargo, en Python, los números complejos no se expresan como un solo valor literal; en cambio consisten en la parte real y la parte imaginaria sumadas juntas; la parte imaginaria se señala con j . literal_eval necesita soportar binario + y - para soportar constantes de números complejos como 1 + 2j o -3.4e-5 - 1.72e9j .

En muchas versiones, incluida Python 3.5, literal_eval es mucho más laxo de lo necesario : acepta cualquier cadena de sumas y restas mientras los lados izquierdo y derecho evalúen cualquier número, por lo tanto (1 + 3) + 2 + (4 - 5) todavía se analiza, incluso si no es una constante compleja que consiste en una parte real + imaginaria.

+ y - no se aceptan incondicionalmente: si intenta agregar 2 listas juntas, fallará, aunque pueda analizar literales de lista, y la adición se define para las listas:

>>> 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]

¿Por qué falla la evaluación literal de 5 * 7 , mientras que 5 + 7 no?

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 ...>

La documentation no explica esto.

Encontré ese problema después de responder esta pregunta en SO: Obtener el resultado de una cadena .


ast.literal_eval() acepta + en los datos evaluados porque 5+2j (número complejo * ) son literales válidos. Lo mismo se aplica a - . Para mantener el código simple, no se intenta excluir + o - como operadores binarios.

No se permiten otros operadores; se supone que la función solo acepta literales, no expresiones.

En otras palabras, que 5 + 7 funciona es un error, pero que es difícil de solucionar sin romper el soporte para construir números complejos. La implementation limita el uso a operandos que son números, unarios + y - , u otros operadores binarios (por lo que no puede usarlos para concatenar listas o producir una diferencia establecida).

También vea varias entradas relacionadas con el rastreador de errores de Python: # 25335 ast.literal_eval no puede analizar los números con los principales "+" , # 22525 ast.literal_eval () no hace lo que dice la documentación y # 4907 ast.literal_eval no maneja adecuadamente los números complejos

* Técnicamente hablando, 2j es un literal válido; Python analiza 5+2j como int(5) binop(+) complex(0, 2) , y solo más tarde produce un objeto complex(5, 2) partir del resultado, cuando realmente ejecuta la suma.