Словари против NamedTuples - PullRequest
       48

Словари против NamedTuples

0 голосов
/ 10 сентября 2018

Помимо словарей, которые изменяются, а NamedTuple нет, этот NamedTuple можно получить по позиции и немного с другой нотацией. Есть ли другие существенные различия между словарями и именованными кортами в Julia? Когда использовать один или другой?

Они кажутся довольно похожими:

# 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]

Ответы [ 3 ]

0 голосов
/ 10 сентября 2018

Думайте о NamedTuple как об анонимном struct у Юлии, а не Dict. В частности, хранение разнородных типов в NamedTuple является стабильным типом.

Обратите внимание, что это также серьезное различие в мышлении между Питоном и Юлией. В Julia, если вы хотите, чтобы ваш код был быстрым, вы обычно заботитесь о выводе типа.

0 голосов
/ 10 сентября 2018

Существенным отличием в Julia является то, что NamedTuple является его собственным типом, и поэтому компилятор может специализироваться на этой конкретной именованной сигнатуре кортежа, в то время как подход «Словарь» должен искать значение по ключу. Кроме того, каждое значение 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
0 голосов
/ 10 сентября 2018

По аналогичным вопросам про Питон кажется .. нет. Основными различиями, по-видимому, является изменчивое / неизменяемое свойство, и то, что x.a более читабелен и менее многословен, чем x [a] ...:

...