Say we have this
>>> x = {'a': 1, 'b': 2}
>>> y = {}
>>> for k, y[k] in x.items(): pass
...
>>> y
{'a': 1, 'b': 2}
Why does this work?
Note: I saw this first here
The straight answer is NO. You can not have duplicate keys in a dictionary in Python.
The dict. copy() method returns a shallow copy of the dictionary. The dictionary can also be copied using the = operator, which points to the same object as the original. So if any change is made in the copied dictionary will also reflect in the original dictionary.
The Key value of a Dictionary is unique and doesn't let you add a duplicate key entry.
We can use loop or dictionary comprehension to remove duplicates from the dictionary in Python. While removing a duplicate value from the dictionary the keys are also removed in the process. If you don't care about retaining the original order then set(my_list) will remove all duplicates.
a, b = (c, d)
unpacks the tuple from left to right and assigns a = c
and b = d
in that order.
x.items()
iterates over key-value pairs in x
. E.g. doing list(x.items())
will give [('a', 1), ('b', 2)]
for a, b in x.items()
assigns the key to a
, and the value to b
for each key-value pair in x
.
for k, y[k] in x.items()
assigns the key to k
, and the value to y[k]
for each key-value pair in x
.
You can use k
in y[k]
because k
has already been assigned since unpacking happens left-right
You don't need to do anything in the loop because whatever you needed is done already.
Because the loop already assigned every value in x
to y[k]
, y
is now a shallow copy of x
.
As the tweet you reference says, this is indeed a "terse, unintuitive, and confusing" way to do x.copy()
This is a remarkably odd way to use the loop binding. For each item, the tuple of (key, value)
is assigned into k, y[k]
. Both instances of k
refer to the same variable, so the subscription y[k]
assigns into the dictionary y
. This relies on a destructuring assignment being solved left to right; using y[k], k
doesn't work as k
isn't assigned the first time through the loop.
The iterating variable is assigned values as it iterates through the iterable. In your case, k, y[k]
are assigned with (key, value)
from dict.items()
.
In your case y[k]
actually calls dict.__setitem__
here which is why your y
gets updated.
Example,
class T():
def __setitem__(self, key, value):
print(f"Assigning {key} with value {value}")
x = {"a": 2, "b": 3, "c": 4}
val = T()
for k, val[k] in x.items():
pass
Assigning a with value 2
Assigning b with value 3
Assigning c with value 4
In your case dict.__setitem__
is called while iterating through x.items()
and dict.__setitem__
mutates your dict y
so eventually you are copying x
dict into y
.
x = {'a': 2, 'b': 3, 'c': 4}
it = iter(x.items())
y = {}
[*iter(lambda : y.__setitem__(*next(it)), "Is this confusing enough??")]
print(y)
# {'a': 2, 'b': 3, 'c': 4}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With