4 Comments
Aug 6Liked by Stephen Gruppetta

The dict (and set) classes are a favorite part of Python. I subclass dict a lot to create self-loading dictionaries and whatnot. Very useful class!

I suppose it isn't an obvious call to the dict constructor, but there is a dict comprehension:

hex_chars = {cx: chr(cx) for cx in range(65, 71)}

Comprehensions being one of the coolest things about Python!

Expand full comment

When using `dict()` to copy a dictionary is it a shallow copy or a deep copy?

Expand full comment
author

Good question. Yes, the default copying tends to be shallow copy since a data structure only contains references to the objects it contains, therefore, the natural way to make a copy of a data structure is to copy those references, which still point to the same original objects.

Here's confirmation:

>>> some_dict = {"first": [1, 2, 3], "second": [4, 5, 6]}

>>> another_dict = dict(some_dict)

>>> another_dict

{'first': [1, 2, 3], 'second': [4, 5, 6]}

>>> another_dict["first"].append(999)

>>> another_dict

{'first': [1, 2, 3, 999], 'second': [4, 5, 6]}

>>> some_dict

{'first': [1, 2, 3, 999], 'second': [4, 5, 6]}

Deep copy required more work! So you need to explicitly choose to use it!

Expand full comment
Aug 6Liked by Stephen Gruppetta

As your example illustrates, both dictionaries contain references to the same string and list objects. Append the list through one, and the other reflects that change. Compare these:

| from copy import deepcopy

| d1 = dict(a=[[[]], [[]]], b=[[[]]])

| d2 = d1.copy()

| d3 = deepcopy(d1)

While d2 refers to the same lists, d3 has copies of the list objects. Changes to the items in d2 are the same as changes to d1, but changes to items in d3 are not. What's perhaps surprising is that even with deepcopy Python reuses the keys. Compare:

| print(list(sorted([id(k) for k in d1.keys()])))

| print(list(sorted([id(k) for k in d2.keys()])))

| print(list(sorted([id(k) for k in d3.keys()])))

With:

| print(list(sorted([id(k) for k in d1.values()])))

| print(list(sorted([id(k) for k in d2.values()])))

| print(list(sorted([id(k) for k in d3.values()])))

(I do wish Substack offered more control over comments. I know these won't turn out the way I typed them in. I inserted vertical pipes to offset the "code".)

Expand full comment