Julia 中有什么东西相当于 Python 的 literal_eval
由包裹提供 ast
(抽象语法树)?
其 ( literal_eval
) 描述摘要:
This function only evaluates Python literal structures: strings, bytes, numbers, tuples, lists, dicts, sets, booleans, and
None
, and can be used for safely evaluating strings from untrusted sources without the need to parse the values oneself. It is not capable of evaluating arbitrarily complex expressions, for example involving operators or indexing.
最佳答案
没有等价物,尽管您可以通过解析代码然后递归地确保在计算结果表达式之前只有某些语法形式,从而很容易地编写一个。然而,与 Python 的许多基本类型及其语法和行为是内置且不可更改的不同,Julia 的“内置”类型只是用户定义的类型,恰好在系统启动之前定义。例如,让我们探讨一下当您使用向量字面量语法时会发生什么:
julia> :([1,2,3]) |> dump
Expr
head: Symbol vect
args: Array{Any}((3,))
1: Int64 1
2: Int64 2
3: Int64 3
typ: Any
julia> f() = [1,2,3]
f (generic function with 2 methods)
julia> @code_lowered f()
CodeInfo(:(begin
nothing
return (Base.vect)(1, 2, 3)
end))
julia> methods(Base.vect)
# 3 methods for generic function "vect":
vect() in Base at array.jl:63
vect(X::T...) where T in Base at array.jl:64
vect(X...) in Base at array.jl:67
所以
[1,2,3]
只是一种句法形式,作为对 Base.vect
的调用而降低函数,即 Base.vect(1,2,3)
.现在,我们可能在 future 可以“密封”一些函数,这样人们就不能以任何方式添加任何子方法或覆盖它们的行为,但目前正在修改 Base.vect
的行为。对于某些参数集是完全可能的:julia> function Base.vect(a::Int, b::Int, c::Int)
warn("SURPRISE!")
return invoke(Base.vect, Tuple{Any,Any,Any}, a, b, c)
end
julia> [1,2,3]
WARNING: SURPRISE!
3-element Array{Int64,1}:
1
2
3
由于数组字面量在 Julia 中是可重载的,因此它并不是真正的纯字面量语法。当然,我不建议做我刚刚做的事情——“惊喜!”不是你想在你的程序中间看到的东西——但它是可能的,因此在这个问题的意义上,语法不是“安全的”。在 Python 或 JavaScript(或大多数脚本语言)中用文字表示的其他一些构造在 Julia 中是显式函数调用,例如构造字典:
julia> Dict(:foo => 1, :bar => 2, :baz => 42)
Dict{Symbol,Int64} with 3 entries:
:baz => 42
:bar => 2
:foo => 1
这只是对
Dict
的函数调用带有三对对象参数的类型,根本不是文字语法。 a => b
pair 语法本身也只是对 =>
的函数调用的特殊语法。运算符,它是 Pair
的别名类型:julia> dump(:(a => b))
Expr
head: Symbol call
args: Array{Any}((3,))
1: Symbol =>
2: Symbol a
3: Symbol b
typ: Any
julia> :foo => 1.23
:foo=>1.23
julia> =>
Pair
julia> Pair(:foo, 1.23)
:foo=>1.23
整数文字呢?这些肯定是安全的!嗯,是和不是。小整数文字目前是安全的,因为它们在解析器中直接转换为
Int
值,没有任何可重载的入口点(但将来可能会改变,允许用户代码为整数文字选择不同的行为)。然而,足够大的整数文字被降级为宏调用,例如:julia> :(18446744073709551616)
:(@int128_str "18446744073709551616")
对于
Int64
来说太大的整数文字类型被降低为带有包含整数数字的字符串参数的宏调用,允许宏解析字符串并返回适当的整数对象 - 在这种情况下是 Int128
值 - 拼接到抽象语法树中。但是您可以为这些宏定义新行为:julia> macro int128_str(s)
warn("BIG SUPRISE!")
9999999999999999
end
julia> 18446744073709551616
WARNING: BIG SUPRISE!
9999999999999999
本质上,Julia 没有有意义的“安全文字子集”。从哲学上讲,Julia 与 Python 非常不同:Julia 不是在一组固定的类型中构建用户定义的类型无法访问的特殊功能,而是在语言中包含足够强大的机制,该语言可以从自身内部构建 - 一个过程被称为“引导”。这些强大的语言机制对 Julia 程序员和 Julia 的程序员来说都是一样的。这就是 Julia 的大部分灵活性和功能的来源。但是,强大的力量伴随着巨大的责任等等......所以除非你有一个很好的理由,否则不要真正做我在这个答案中做过的任何事情:)
回到您最初的问题,使用 Julia 语法为安全文字对象构造创建解析器的最佳方法是为 Julia 的子集实现解析器,以无法重载的方式赋予文字通常的含义。这个安全的语法子集可以包括数字文字、字符串文字、数组文字和
Dict
构造函数,例如。但仅使用 JSON 语法并使用 Julia 的 JSON package 解析它可能更实用。 .
关于python - Julia 中 Python 的 ast.literal_eval() 相当于什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44194951/