简体   繁体   English

为什么 dict.get(key) 有效但 dict[key] 无效?

[英]Why did dict.get(key) work but not dict[key]?

I'm trying to group together the binary strings of certain numbers based on how many 1's there are in the string.我试图根据字符串中有多少个 1 将某些数字的二进制字符串组合在一起。

This doesn't work:这不起作用:

s = "0 1 3 7 8 9 11 15"
numbers = map(int, s.split())
binaries = [bin(x)[2:].rjust(4, '0') for x in numbers]

one_groups = dict.fromkeys(range(5), [])
for x in binaries:
    one_groups[x.count('1')] += [x]

The expected dictionary one_groups needs to be预期的字典one_groups需要是

{0: ['0000'], 
 1: ['0001', '1000'], 
 2: ['0011', '1001'], 
 3: ['0111', '1011'], 
 4: ['1111']}

But I get但我明白了

{0: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111'], 
 1: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111'], 
 2: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111'], 
 3: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111'], 
 4: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111']}

So far the only thing that has worked is if I use one_groups[x.count('1')] = one_groups.get(x.count('1')) + [x] instead of one_groups[x.count('1')] += [x]到目前为止,唯一有效的是如果我使用one_groups[x.count('1')] = one_groups.get(x.count('1')) + [x]而不是one_groups[x.count('1')] += [x]

But why is that so?但为什么会这样呢? If I recall correctly, isn't dict[key] supposed to return the value of that dictionary, similar to how dict.get(key) works?如果我没记错的话, dict[key]不应该返回该字典的值,类似于dict.get(key)的工作原理吗? I've seen this thread Why dict.get(key) instead of dict[key]?我看过这个线程为什么用 dict.get(key) 而不是 dict[key]? but it didn't answer my question for this particular case, since I know for sure the program isn't meant to get the KeyError但它没有回答我针对这种特殊情况的问题,因为我确定该程序并不意味着获取KeyError

I have also tried one_groups[x.count('1')].append(x) but this doesn't work either.我也试过one_groups[x.count('1')].append(x)但这也不起作用。

The problem is mutability:问题是可变性:

one_groups = dict.fromkeys(range(5), []) - this passes the same list as value to all keys . one_groups = dict.fromkeys(range(5), []) - 这会将与 value 相同的列表传递给所有 keys So if you change one value, you change them all.因此,如果您更改一个值,则将它们全部更改。

It's basically the same as saying:这与说的基本相同:

tmp = []
one_groups = dict.fromkeys(range(5), tmp)
del tmp

If you want to use a new list, you need to do it in a loop - either an explicit for loop or in a dict comprehension:如果你想使用一个新的列表,你需要在一个循环中进行 - 一个显式for循环或一个 dict 理解:

one_groups = {key: [] for key in range(5)}

This thing will "execute" [] (which equals to list() ) for every key, thus making the values with different lists.这个东西将为每个键“执行” [] (等于list() ),从而使值具有不同的列表。


Why does get work?为什么会get工作? Because you explicitly take the current list, but + makes a new result list.因为您显式地获取当前列表,但是+生成了一个新的结果列表。 And it doesn't matter whether it's one_groups[x.count('1')] = one_groups.get(x.count('1')) + [x] or one_groups[x.count('1')] = one_groups[x.count('1')] + [x] - what matters is that there's + .不管是one_groups[x.count('1')] = one_groups.get(x.count('1')) + [x]还是one_groups[x.count('1')] = one_groups[x.count('1')] + [x] - 重要的是有+

I know how everybody says a+=b is just a=a+b , but the implementation may be different for optimisation - in case of lists, += is just .extend because we know we want our result in the current variable, so creating new list would be waste of memory.我知道每个人都怎么说a+=b只是a=a+b ,但是优化的实现可能会有所不同 - 在列表的情况下, +=只是.extend因为我们知道我们希望我们的结果在当前变量中,所以创建新列表将浪费 memory。

The problem is using one_groups = dict.fromkeys(range(5), [])问题是使用one_groups = dict.fromkeys(range(5), [])

(This passes the same list as value to all keys. So if you change one value, you change them all) (这会将相同的列表作为值传递给所有键。因此,如果您更改一个值,则将它们全部更改)


You can use this instead: one_groups = {i:[] for i in range(5)}您可以改用它: one_groups = {i:[] for i in range(5)}

(This thing will "execute" [] (which equals to list()) for every key, thus making the values with different lists.) (这个东西将为每个键“执行”[](等于 list()),从而使值具有不同的列表。)

This is the help on dict's fromkeys method.这是 dict 的fromkeys方法的帮助。

Help on built-in function fromkeys:内置 function 的帮助来自keys:

fromkeys(iterable, value=None, /) method of builtins.type instance Create a new dictionary with keys from iterable and values set to value fromkeys(iterable, value=None, /) 方法 builtins.type 实例创建一个新字典,其中键来自 iterable,值设置为 value

That says that fromkeys will accept a value, and even it is a callable, it will evaluate it first, and then assign that value to all the dict keys.这表示 fromkeys 将接受一个值,即使它是可调用的,它也会首先评估它,然后将该值分配给所有 dict 键。

Lists are mutable in Python, and so it will assign the same empty list reference and one change will affect them all. Python 中的列表是可变的,因此它将分配相同的空列表引用,并且一项更改将影响所有列表。

Use defaultdict instead as so:改为使用 defaultdict :

>>> from collections import defaultdict
>>> one_groups = defaultdict(list)
>>> for x in binaries:
      one_groups[x.count('1')] += [x]
>>> one_groups = dict(one_groups) # to stop default dict behavior

This will accept assignments to non-existing keys and values will default to empty lists (in this case).这将接受分配给不存在的键和值将默认为空列表(在这种情况下)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM