With the ruby code, you are creating a new Hash (the Python equivalent would be a dictionary) with a dynamic default value which is defined by the lambda passed to Hash.new. In Python, this could be regarded as an (anonymous) function being passed to the constructor.
This lambda (with some indirections which shall not be important here) is called each time an undefined key is accessed in the hash. The value returned by the lambda is assumed to be the value of the key. The lambda has also the side effect of adding the default value to the hash.
This thus works quite similarly to the defaultdict collection in Python.
Now, the default value will always be a new hash object which again is setup to set and return new hash objects when an undefined key is accessed:
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"}}}
I believe the equivalent Python data structure would be something like this defaultdict:
from collections import defaultdict
x = lambda defaultdict(lambda: x())
abc = defaultdict(lambda: x())
Hash.new(something)is analogous tocollections.defaultdict(lambda: something)