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