Julia中Python的ast.literal_eval()相当于什么?

时间:2017-05-26 06:24:08

标签: python julia abstract-syntax-tree type-conversion

Julia中有什么东西相当于包ast(抽象语法树)提供的Python literal_eval吗?

其(literal_eval)描述摘要:

  

此函数仅评估Python文字结构:字符串,   字节,数字,元组,列表,dicts,集合,布尔值和None,以及   可用于安全地评估来自不受信任来源的字符串   无需自己解析价值观。它无法做到   评估任意复杂的表达式,例如涉及   运营商或索引。

2 个答案:

答案 0 :(得分:14)

没有等价物,虽然你可以通过解析代码然后递归地确保在评估它之前在结果表达式中只有某些语法形式,从而可以很容易地编写一个。但是,与许多基本类型及其语法和行为内置且不可更改的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)。现在,我们将来可能会“封锁”某些函数,以便无法以任何方式添加任何子方法或覆盖它们的行为,但是当前为某些参数修改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运算符是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 值 - 要拼接到抽象语法树中。但您可以为这些宏定义新行为:

Dict

基本上,朱莉娅没有有意义的“安全文字子集”。从哲学上讲,Julia与Python非常不同:Julia不是在具有用户定义类型无法访问的特殊功能的固定类型集中构建,而是在语言中包含足够强大的机制,可以从内部构建语言 - 一个过程被称为“自举”。这些强大的语言机制与Julia程序员一样,对Julia的程序员也是如此。这就是朱莉娅的灵活性和力量的来源。但是,强大的力量带来了巨大的责任和所有......所以除非你有真的正当理由,否则不要做我在这个答案中所做的任何事情:)

要回到原来的问题,使用Julia语法为安全文字对象构造创建解析器最好的方法是为Julia的子集实现解析器,为文字提供通常的意思是不能超载的方式。例如,此安全语法子集可以包括数字文字,字符串文字,数组文字和puts("\033[31m"); 构造函数。但是使用JSON语法并使用Julia的JSON package解析它可能更实际。

答案 1 :(得分:1)

我知道我来晚了,但是[program:apache] command=/usr/bin/pidproxy /var/run/apache2/apache2.pid /bin/bash -c "/usr/sbin/apache2ctl -D FOREGROUND" autorestart=true 完成了工作:

Meta.parse

具体来说, julia> eval(Meta.parse("[1,2,3]")) 3-element Array{Int64,1}: 1 2 3 将字符串转换为Meta.parse,然后Expr转换为可用的数据结构。绝对可以在Julia 1.0中使用。 https://discourse.julialang.org/t/how-to-convert-a-string-into-an-expression/11160