Julia 中 Python 的 ast.literal_eval() 的等价物是什么?
What is the equivalent of Python's ast.literal_eval() in Julia?
Julia 中有什么等同于包 ast
(抽象语法树)提供的 Python 的 literal_eval
吗?
其(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 的 "built in" 类型只是用户定义的类型,恰好在系统启动之前定义。让我们探讨一下会发生什么,例如,当您使用向量文字语法时:
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)
。现在,我们将来可能会 "seal" 一些函数,这样就不能添加任何子方法或以任何方式覆盖它们的行为,但目前正在修改 Base.vect
的一些行为arguments 是完全可以的:
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 中是可重载的,因此它并不是真正的纯文字语法。当然,我不建议做我刚才做的事情——"SURPRISE!" 不是你想在程序中间看到的东西——但这是可能的,因此语法不是 "safe"这个问题的感觉。 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
类型的别名:
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
类型来说太大的整数文字被降低为带有包含整数数字的字符串参数的宏调用,允许宏解析字符串和 return 适当的整数对象——在本例中是一个 Int128
值——要拼接到抽象语法树中。但是您可以为这些宏定义新的行为:
julia> macro int128_str(s)
warn("BIG SUPRISE!")
9999999999999999
end
julia> 18446744073709551616
WARNING: BIG SUPRISE!
9999999999999999
本质上,Julia 没有什么意义"safe literal subset"。从哲学上讲,Julia 与 Python 非常不同:Julia 不是构建具有用户定义类型无法访问的特殊功能的一组固定类型,而是在语言中包含足够强大的机制,可以从内部构建语言本身——一个称为 "bootstrapping" 的过程。这些强大的语言机制对 Julia 程序员和 Julia 程序员一样可用。这就是 Julia 的大部分灵活性和强大功能的来源。但是能力越大,责任越大......所以,除非你有 真的 充分理由,否则不要实际做我在这个答案中所做的任何事情 :)
回到原来的问题,使用 Julia 语法为安全文字对象构造创建解析器的最佳方法是为 Julia 的子集实现解析器,为文字提供 usual 意味着无法重载。例如,此安全语法子集可以包括数字文字、字符串文字、数组文字和 Dict
构造函数。但是只使用 JSON 语法并使用 Julia 的 JSON package.
解析它可能会更实用
我知道我来晚了,但是 Meta.parse
完成了工作:
julia> eval(Meta.parse("[1,2,3]"))
3-element Array{Int64,1}:
1
2
3
具体来说,Meta.parse
将您的字符串转换为 Expr
,然后 eval
将其转换为可用的数据结构。绝对适用于 Julia 1.0。
https://discourse.julialang.org/t/how-to-convert-a-string-into-an-expression/11160
Julia 中有什么等同于包 ast
(抽象语法树)提供的 Python 的 literal_eval
吗?
其(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 的 "built in" 类型只是用户定义的类型,恰好在系统启动之前定义。让我们探讨一下会发生什么,例如,当您使用向量文字语法时:
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)
。现在,我们将来可能会 "seal" 一些函数,这样就不能添加任何子方法或以任何方式覆盖它们的行为,但目前正在修改 Base.vect
的一些行为arguments 是完全可以的:
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 中是可重载的,因此它并不是真正的纯文字语法。当然,我不建议做我刚才做的事情——"SURPRISE!" 不是你想在程序中间看到的东西——但这是可能的,因此语法不是 "safe"这个问题的感觉。 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
类型的别名:
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
类型来说太大的整数文字被降低为带有包含整数数字的字符串参数的宏调用,允许宏解析字符串和 return 适当的整数对象——在本例中是一个 Int128
值——要拼接到抽象语法树中。但是您可以为这些宏定义新的行为:
julia> macro int128_str(s)
warn("BIG SUPRISE!")
9999999999999999
end
julia> 18446744073709551616
WARNING: BIG SUPRISE!
9999999999999999
本质上,Julia 没有什么意义"safe literal subset"。从哲学上讲,Julia 与 Python 非常不同:Julia 不是构建具有用户定义类型无法访问的特殊功能的一组固定类型,而是在语言中包含足够强大的机制,可以从内部构建语言本身——一个称为 "bootstrapping" 的过程。这些强大的语言机制对 Julia 程序员和 Julia 程序员一样可用。这就是 Julia 的大部分灵活性和强大功能的来源。但是能力越大,责任越大......所以,除非你有 真的 充分理由,否则不要实际做我在这个答案中所做的任何事情 :)
回到原来的问题,使用 Julia 语法为安全文字对象构造创建解析器的最佳方法是为 Julia 的子集实现解析器,为文字提供 usual 意味着无法重载。例如,此安全语法子集可以包括数字文字、字符串文字、数组文字和 Dict
构造函数。但是只使用 JSON 语法并使用 Julia 的 JSON package.
我知道我来晚了,但是 Meta.parse
完成了工作:
julia> eval(Meta.parse("[1,2,3]"))
3-element Array{Int64,1}:
1
2
3
具体来说,Meta.parse
将您的字符串转换为 Expr
,然后 eval
将其转换为可用的数据结构。绝对适用于 Julia 1.0。
https://discourse.julialang.org/t/how-to-convert-a-string-into-an-expression/11160