除了Dictionary是可变的而且不是NamedTuple之外,NamedTuple可以通过位置和一些不同的符号来检索,Julia中的Dictionary和NamedTuples之间是否存在 other 显着差异?什么时候使用其中一个?
它们看起来很相似:
# Definition
d = Dict("k1"=>"v1", "k2"=>"v2")
nt = (k1="v1", k2="v2")
# Selection by specific key
d["k1"]
nt.k1
# Keys
keys(d)
keys(nt)
# Values
values(d)
values(nt)
# Selection by position
d[1] # error
nt[1]
答案 0 :(得分:5)
Julia的一个显着区别是NamedTuple是它自己的类型,因此编译器可以专注于该特定的命名元组签名,而Dictionary方法必须从键中查找值。另外,NamedTuple的每个值本身可以是不同的类型,从而可以实现进一步的优化和类型稳定性,而这在字典中是无法实现的。如果我们对其稍作更改,以使字典的类型是异构的,从而使它的类型为Dict{Symbol,Any}
,则可以看到它如何仍然是类型稳定的。
d=Dict(:k1=>"v1",:k2=>2.0)
nt=(k1="v1",k2=2.0)
foo(x) = x[:k2]
现在,如果函数使用此字典或直接命名为元组的函数,我们可以看到字典类型的结果不是稳定的,因为字典中的值只能由Any
的类型来保证
@code_warntype foo(d)
Body::Any
4 1 ─ %1 = invoke Base.ht_keyindex(_2::Dict{Symbol,Any}, :k2::Symbol)::Int64 │╻ getindex
│ %2 = (Base.slt_int)(%1, 0)::Bool ││╻ <
└── goto #3 if not %2 ││
2 ─ %4 = %new(Base.KeyError, :k2)::KeyError ││╻ Type
│ (Base.throw)(%4) ││
└── $(Expr(:unreachable)) ││
3 ─ %7 = (Base.getfield)(x, :vals)::Array{Any,1} ││╻ getproperty
│ %8 = (Base.arrayref)(false, %7, %1)::Any ││╻ getindex
└── goto #5 ││
4 ─ $(Expr(:unreachable)) ││
5 ┄ return %8
另一方面,NamedTuple可以是类型稳定的。因为该字段是函数已知的,所以类型也称为Float64
。
@code_warntype foo(nt)
Body::Float64
4 1 ─ %1 = (Base.getfield)(x, :k2)::Float64 │╻ getindex
└── return %1
答案 1 :(得分:4)
将NamedTuple
视为Julia中的匿名struct
,而不是Dict
。特别是在NamedTuple
中存储异构类型是类型稳定的。
请注意,这也是Python和Julia之间思维上的主要差异。在Julia中,如果您希望代码快速运行,通常会关心类型推断。
答案 2 :(得分:-2)
根据关于Python的类似问题似乎..不是。主要区别似乎是可变/不可变属性,并且x.a比x [a] ...更易读,更不冗长: