Search code examples
pythondefaultdict

Python defaultdict weird behavior when using string key


Sorry if this has been answered before but it's hard to explain this situation in one sentence, so my search doesn't yield any good result.

I was trying to solve LeetCode 1048. And you can see my solution below. I felt my solution works logically. However, when I ran it the result always comes short.

Therefore, I tried to debug it buying doing print(dp[newWord]) in the middle of the loop, and then it magically worked. In fact you don't even have to print it, just typing it in the code to access it can make it work.

Could someone explain to me why defaultdict has this behavior? I've used it extensively and I don't recall having this issue before...

import collections

def longestStrChain(words):
    words.sort(key=lambda word: (len(word), word))
    dp = collections.defaultdict(int)
    result = 1
    
    for word in words:
        if len(word) == 1:
            dp[word] = 1
        else:
            for i in range(len(word)):
                newWord = str(word[:i] + word[i+1:])
                # dp[newWord] # uncomment this line and it will work
                if newWord in dp:
                    dp[word] = max(dp[word], dp[newWord] + 1)
                    result = max(result, dp[word])
                else:
                    dp[word] = 1
                
    return result

print(longestStrChain(["a","b","ba","bca","bda","bdca"]))
# expecting 4, but always getting 3 until I uncomment the line

Solution

  • Once you do dp[newWord], newWord in dp is True. See the documentation:

    __missing__(key)

    ...

    If default_factory is not None, it is called without arguments to provide a default value for the given key, this value is inserted in the dictionary for the key, and returned.

    (added bold)