Skip to content

Python Dictionaries

Python Data Structures

Copying

Deep copying

import copy
deep_copy = copy.deepcopy()

Shallow copying

>>> a = {1:1}
>>> b = {2:2}
>>> c = dict({'a': a, 'b': b})
>>> a[3] = 3
>>> c
{'a': {1: 1, 3: 3}, 'b': {2: 2}}

Deep copying dicts

Does dict have key?

>>> 'key' in my_dict
False

>>> my_dict.get('key')
None

>>> my_dict.get('key', 1)
1

Nested get

example_dict.get('key1', {}).get('key2')
  • default fallback for .get is None
    • unlike getattr
    • which you have to explicitly provide a fallback

Merge Dictionaries

Python 3.10: Set Union Notation

merged = dict1 | dict2 | dict3

Before Python 3.10

merged = {**dict1, **dict2, **dict3}

Destructure dicts

In JS

params = { a: 1, b: 2 };
const { a, b } = params;

Python can't do the same thing 😞

Given params = {'a': 1, 'b': 2}

itemgetter

from operator import itemgetter
a, b = itemgetter('a', 'b')(params)

list comprehension

a, b = [d[k] for k in ('a','b')]

assignment

a, b = params['a'], params['b']

key with the max value

d = {'a': 1, 'b': 3000, 'c': 0}
max(stats, key=d.get)  # 'b'

max(stats, key=lambda key: d[key])  # 'b'

Sorting by keys

  • Python 3.6+: sorted by insertion order
  • to sort, convert to to dict_items
    • an iterator (kinda like a list of tuples)
>>> d.items()
dict_items([('a', 1), ('b', 3000), ('c', 0)])
>>> sorted(d.items(), key=lambda x: x[1])
[('c', 0), ('a', 1), ('b', 3000)]

same as

import operator
>>> sorted(d.items(), key=operator.itemgetter(1))
[('c', 0), ('a', 1), ('b', 3000)]

The Craziest Dict Expression

>>> {True: 'yes', 1: 'no', 1.0: 'maybe'}
{True: 'maybe'}
  • bool is implemented as a special int
    • True == 1 == 1.0
    • hash(True) == hash(1) == hash(1.0)
  • dict is looking for a key that matches the same
    • __hash__
    • __eq__
  • so it overrides the value
  • keeps True as the key because that was the first key
    • no point in updating the key's representation if it's gonna be the same

defaultdict

my_dict = collections.defaultdict(int)  # default value: 0
my_dict[key] += 1

ChainMap

Maintaining a precedence chain of defaults

cli_args = {"debug": True}
defaults = {"debug": False}

config = ChainMap(cli_args, defaults)
config["debug"]  # True

# looks for the key in cli_args and then in defaults

MappingProxyType

  • read-only immutable dictionaries
  • not hashable
    • unlike namedtuple
  • example
    • dict of internal state that you don't
from types import MappingProxyType
writable = {'one': 1, 'two': 2}
read_only = MappingProxyType(writable)

>>> read_only['one']
1
>>> read_only['one'] = 23
TypeError:
"'mappingproxy' object does not support item assignment"
# Updates to the original are reflected in the proxy:
>>> writable['one'] = 42
>>> read_only
mappingproxy({'one': 42, 'two': 2})

UserDict

When you want to modify the behaviour of the built-in dict???


Last update: 2023-04-24