389

I'd like to get from this:

keys = [1,2,3]

to this:

{1: None, 2: None, 3: None}

Is there a pythonic way of doing it?

This is an ugly way to do it:

>>> keys = [1,2,3]
>>> dict([(1,2)])
{1: 2}
>>> dict(zip(keys, [None]*len(keys)))
{1: None, 2: None, 3: None}
1
  • Do you intend for the dictionary to have None values for all keys? If so, why not use a set instead? The only reason that comes to mind for using a dict instead of set in this case is if you want to iterate the structure in insertion order. Commented Aug 7, 2022 at 14:08

7 Answers 7

569

dict.fromkeys directly solves the problem:

>>> dict.fromkeys([1, 2, 3, 4])
{1: None, 2: None, 3: None, 4: None}

This is actually a classmethod, so it works for dict-subclasses (like collections.defaultdict) as well.

The optional second argument, which defaults to None, specifies the value to use for the keys. Note that the same object will be used for each key, which can cause problems with mutable values:

>>> x = dict.fromkeys([1, 2, 3, 4], [])
>>> x[1].append('test')
>>> x
{1: ['test'], 2: ['test'], 3: ['test'], 4: ['test']}

If this is unacceptable, see How can I initialize a dictionary whose values are distinct empty lists? for a workaround.

Sign up to request clarification or add additional context in comments.

4 Comments

Be careful with initializing to something mutable: If you call, e.g., dict.fromkeys([1, 2, 3], []), all of the keys are mapped to the same list, and modifying one will modify them all.
Initializing with {k:[] for k in [1, 2, 3]} is still safe though.
@charleslparker are you sure of this? I tried to initialize a dictionary from a list, then changed the first element in the list (mutate it). The dictionary keys weren't affected.
@ReslanTinawi It's not about the keys. If you would add something to the list corresponding to the first key, then it would also be added to the lists belonging to the other keys; because they all reference the same list.
365

Use a dict comprehension:

>>> keys = [1,2,3,5,6,7]
>>> {key: None for key in keys}
{1: None, 2: None, 3: None, 5: None, 6: None, 7: None}

The value expression is evaluated each time, so this can be used to create a dict with separate lists (say) as values:

>>> x = {key: [] for key in [1, 2, 3, 4]}
>>> x[1] = 'test'
>>> x
{1: 'test', 2: [], 3: [], 4: []}

7 Comments

I believe it was backported to 2.7
This is nice and doesn't suffer from the reference issue that the accepted answer does.
This also allows you to assign a default value (e.g. False).
This is the cleanest, most Pythonic way in Python3 IMO
Using a dict-comp also allows the value to be the result of calling a function (which could be passed the key as an argument, if desired) — so is a very powerful mechanism.
|
87
dict.fromkeys(keys, None)

4 Comments

awesome, i wanted empty lists, dict.fromkeys(keys, [])
@muon That is almost certainly not what you want, see charleslparker comment.
Works in Python version 2.6.6.
Beware: this will initialize dict with all keys points to same single value
25

A list comprehension can be used to build a list of key-value pairs, which can then be passed to the dict constructor. Thus:

>>> keys = {"a", "b", "c", "d"}
>>> d = dict([(key, []) for key in keys])
>>> d
{'d': [], 'c': [], 'a': [], 'b': []}

The value expression is evaluated each time, creating separate lists in the above example:

>>> d['a'].append('test')
>>> d
{'d': [], 'c': [], 'a': ['test'], 'b': []}

3 Comments

While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value.
the name keyDict is misleading, as the first line of code returns a set, not a dict.
They probably will be mapped to the same list though
16

Simply iterate and add the values to an empty dictionary:

d = {}
for i in keys:
    d[i] = None

Comments

10

In many workflows where you want to attach a default / initial value for arbitrary keys, you don't need to hash each key individually ahead of time. You can use collections.defaultdict. For example:

from collections import defaultdict

d = defaultdict(lambda: None)

print(d[1])  # None
print(d[2])  # None
print(d[3])  # None

This is more efficient, it saves having to hash all your keys at instantiation. Moreover, defaultdict is a subclass of dict, so there's usually no need to convert back to a regular dictionary.

For workflows where you require controls on permissible keys, you can use dict.fromkeys as per the accepted answer:

d = dict.fromkeys([1, 2, 3, 4])

Comments

1

Just because it's fun how the dict constructor works nicely with zip, you can repeat the default value and zip it to the keys:

from itertools import repeat

keys = [1, 2, 3]
default_value = None

d = dict(zip(keys, repeat(default_value)))
print(d)

Will give:

{1: None, 2: None, 3: None}

repeat creates an infinite iterator of the element passed to it but as zip stops on the shortest iterable all works well.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.