Nick
Nick

Reputation: 3124

Strange syntax in python dictionary construction - can you explain?

I'm looking at someone else's Python code and saw the following expression:

dp = defaultdict(lambda: inf, {(): 0})

What does it mean?

I am familiar with defaultdict - defaultdict(lambda: inf) would create a dictionary with a default value of inf. But what about the second argument: {(): 0} ? What is its meaning?

EDIT:

I saw this line in the following code. So, I guess, I am trying to understand what is this good for. The author is not responsive so I am trying to understand the rationale and the potential benefits of using this syntax.

EDIT2: I realised that this line is simply equivalent to

dp = defaultdict(lambda: 0)
dp[()] = 0

The main advantage of this syntax is its shortness - it accomplishes this in a single line of code. I simply wasn't aware that you can define a defaultdict and, simultaneously, add an entry in it.

Now, the second argument in the constructor (using an empty tuple as a key for a dictionary entry) is still unusual. But it is just an odd choice - there is nothing new per se in this syntax.

PS. I accepted Patrick's post even as it is not providing the exact answer I was looking for. It still gave me some guidance.

Upvotes: 1

Views: 81

Answers (1)

Patrick Artner
Patrick Artner

Reputation: 51623

It creates a default dict with tuples of (item:inf, {():0})?

Why not simpy add one item and see for yourself?

from collections import defaultdict
from math import inf
dp = defaultdict(lambda: inf, {(): 0})

dp[42]
print(dp) 

Output:

defaultdict(<function <lambda> at 0x7f5b389a7e18>, {(): 0, 42: inf})

Added a print statement to this into the helper call

from collections import Counter, defaultdict
from math import inf, isinf
from pprint import pprint

class Solution(object):
    def minStickers(self, stickers, target):
        s_cnts = *map(Counter, stickers),
        dp = defaultdict(lambda: inf, {(): 0})
        def helper(cnt):
            _id = tuple(cnt.items())
            if isinf(dp[_id]):
                dp[_id] = 1 + min((helper(cnt - s_cnt) for s_cnt in s_cnts 
                                  if s_cnt[_id[0][0]]), default=inf)
            pprint(dp)
            return dp[_id]

        # no python 3.8 available, replaced walrussoperator  
        return -1 if isinf( helper(Counter(target))) else helper(Counter(target))

s = Solution()

print(s.minStickers(["with", "example", "science"], "thehat"))

leads to

defaultdict(<function Solution.minStickers.<locals>.<lambda> at 0x03A4C4F8>,
            {(): 0,
             (('e', 1), ('a', 1)): inf,
             (('t', 1), ('h', 1), ('e', 1), ('a', 1)): inf,
             (('t', 2), ('h', 2), ('e', 1), ('a', 1)): inf})

defaultdict(<function Solution.minStickers.<locals>.<lambda> at 0x03A4C4F8>,
            {(): 0,
             (('a', 1),): inf,
             (('e', 1), ('a', 1)): inf,
             (('t', 1), ('h', 1), ('e', 1), ('a', 1)): inf,
             (('t', 2), ('h', 2), ('e', 1), ('a', 1)): inf})

defaultdict(<function Solution.minStickers.<locals>.<lambda> at 0x03A4C4F8>,
            {(): 0,
             (('a', 1),): 1,
             (('e', 1), ('a', 1)): inf,
             (('t', 1), ('h', 1), ('e', 1), ('a', 1)): inf,
             (('t', 2), ('h', 2), ('e', 1), ('a', 1)): inf})

defaultdict(<function Solution.minStickers.<locals>.<lambda> at 0x03A4C4F8>,
            {(): 0,
             (('a', 1),): 1,
             (('e', 1), ('a', 1)): 1,
             (('t', 1), ('h', 1), ('e', 1), ('a', 1)): inf,
             (('t', 2), ('h', 2), ('e', 1), ('a', 1)): inf})

defaultdict(<function Solution.minStickers.<locals>.<lambda> at 0x03A4C4F8>,
            {(): 0,
             The thread 'MainThread' (0x1) has exited with code 0 (0x0).
(('a', 1),): 1,
             (('e', 1), ('a', 1)): 1,
             (('t', 1), ('h', 1), ('e', 1), ('a', 1)): 2,
             (('t', 2), ('h', 2), ('e', 1), ('a', 1)): inf})

defaultdict(<function Solution.minStickers.<locals>.<lambda> at 0x03A4C4F8>,
            {(): 0,
             (('a', 1),): 1,
             (('e', 1), ('a', 1)): 1,
             (('t', 1), ('h', 1), ('e', 1), ('a', 1)): 2,
             (('t', 2), ('h', 2), ('e', 1), ('a', 1)): 3})

Upvotes: 1

Related Questions