Python でのネストされた Ruby ハッシュ

概要

誰か、このコードが Ruby で何をするのか説明してもらえますか?

x = ->(h, k) { h[k] = Hash.new(&x) }
@abc = Hash.new(&x)

検索しましたが、実際に何が起こっているのかわかりませんでした。 ネストされたハッシュを作成することを目的としているのでしょうか?

また、Python で書きたい場合、これはどのように変換されるでしょうか?

解決策

Ruby コードを使用すると、Hash.new に渡されるラムダによって定義される動的なデフォルト値を使用して、新しいハッシュ (Python に相当するものは辞書) を作成します。 Python では、これはコンストラクターに渡される (匿名の) 関数とみなすことができます。

このラムダ (ここでは重要ではないいくつかの間接指定を伴います) は、ハッシュ内の未定義のキーがアクセスされるたびに呼び出されます。ラムダによって返される値はキーの値であるとみなされます。ラムダには、ハッシュにデフォルト値を追加するという副作用もあります。

したがって、これは Python の defaultdict コレクションと非常によく似た働きをします。

現在、デフォルト値は常に新しいハッシュ オブジェクトになり、未定義のキーがアクセスされたときに新しいハッシュ オブジェクトを設定して返すように再度設定されます。

x = ->(h, k) { h[k] = Hash.new(&x) }
@abc = Hash.new(&x)

@abc[:a]
# => {}

@abc[:b]
# => {}

@abc[:a].equal? @abc[:a]
=> true

@abc[:a].equal? @abc[:b]
=> false

@abc[:custom] = 123
@abc[:x][:y][:z] = 'abc'
@abc
# => {:a=>{}, :b=>{}, :custom=>123, :x=>{:y=>{:z=>"abc"}}}

同等の Python データ構造は次の defaultdict のようなものになると思います。

from collections import defaultdict

x = lambda defaultdict(lambda: x())
abc = defaultdict(lambda: x())