
Hashing it Out - barbierocks
https://akshayr.me/blog/articles/python-dictionaries
======
barbierocks
Here's a cute follow-up: what are all possible outputs of the following
program?

    
    
        import random
    
        class C:
            def __hash__(self): 
                # return 0 or 1, with equal probability
                return random.randint(0, 1)
    
        x = C()
        d = {}
    
        d[x] = "foo"
        d[x] = "bar"
        d[x] = "baz"
    
        print(len(d), d[x])

~~~
infogulch

        1 baz
        1 None (?)
        2 foo
        2 bar
        2 baz
    

If __hash__(x) is recalculated on every indexing (?).

~~~
barbierocks
Essentially correct! Instead of `1 None` it'd fail with a `KeyError`. You can
get a probability distribution too:

    
    
        1 baz       1/8
        KeyError    1/8
        2 foo       1/8
        2 bar       1/4
        2 baz       3/8

~~~
divbzero
Indeed, I got

    
    
      Counter({
          (1, 'baz'): 12525,
          (1, 'KeyError'): 12552,
          (2, 'foo'): 12255,
          (2, 'bar'): 25282,
          (2, 'baz'): 37386
      })
    

from running

    
    
      import random
      
      class C:
          def __hash__(self): 
              # return 0 or 1, with equal probability
              return random.randint(0, 1)
      
      def output():
          x = C()
          d = {}
          d[x] = "foo"
          d[x] = "bar"
          d[x] = "baz"
          try:
              return len(d), d[x]
          except Exception as e:
              return len(d), type(e).__name__
      
      from collections import Counter
      Counter(output() for i in range(100000))

------
DabbyDabberson
The real treasure of akshayr.me:

[https://akshayr.me/snoop/](https://akshayr.me/snoop/)

~~~
barbierocks
LOL

