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

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

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/

相关文章:

python - pandas 从日期时间索引中删除秒

python - 绘图未偏移屏幕

arrays - 如何将列表中的元素重复n次?

julia - 在 Julia 的一行( block 除外)中捕获多个异常?

javascript - 如何通过语句静态验证 JS 构造语句

python - 如何从.exe文件中删除用python编写的.exe文件?

Django 中的 Java 应用程序上下文

combinatorics - Julia:带有替换的唯一 n 个元素集

java - ANTLR 4 和 AST 访问者

java - 提取Java注释正文(不带//、/*、*/)