使用" + ="在计数器数组中导致了一个意外的行为,Python

时间:2014-09-14 04:06:55

标签: python operators

我正在使用Python 3.4.1,我想知道以下情况:

给出一组计数器

cnt = [Counter()] * n

我想在特定位置添加一些项目,所以我做

cnt[i] += Counter(x)

对于施工“+ =”,我试图做

cnt[i] = cnt[i] + Counter(x)

但是,而不是我的预期,我收到了相当于

的东西
for i in range(0, n):
    cnt[i] = cnt[i] + Counter(x)

换句话说,它在阵列中添加了我的所有计数器。

  • 这种行为(添加数组中的每个项目)在Python中是否常见? 我在解释任何错误吗?
  • 有一种正确/简单/安全的方式来写我想要的东西吗?
  • 这是版本的错误吗?

一个简短的例子:

from collections import Counter

text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
cnt = [Counter()] * 2

i = 0
for c in text:
    cnt[i] += Counter(c)  # cnt[i] = cnt[i] + Counter(c)
    i = (i+1) % 2

for i in range(0, 2):
    print(cnt[i], i)

输出:

Counter({' ': 7, 'i': 6, 'e': 5, 't': 5, 'o': 4, 's': 4, 'm': 3, 'r': 3, 'c': 3, 'u': 2, 'p': 2, 'a': 2, 'l': 2, 'd': 2, 'n': 2, '.': 1, 'g': 1, 'L': 1, ',': 1}) 0
Counter({' ': 7, 'i': 6, 'e': 5, 't': 5, 'o': 4, 's': 4, 'm': 3, 'r': 3, 'c': 3, 'u': 2, 'p': 2, 'a': 2, 'l': 2, 'd': 2, 'n': 2, '.': 1, 'g': 1, 'L': 1, ',': 1}) 1

预期产出:

Counter({'t': 4, 'i': 3, 'r': 3, 's': 2, 'e': 2, 'm': 2, 'c': 2, 'n': 2, 'a': 2, 'l': 2, ',': 1, 'd': 1, ' ': 1, 'L': 1}) 0
Counter({' ': 6, 'o': 4, 'i': 3, 'e': 3, 's': 2, 'u': 2, 'p': 2, '.': 1, 't': 1, 'g': 1, 'd': 1, 'm': 1, 'c': 1}) 1

1 个答案:

答案 0 :(得分:1)

执行cnt = [Counter()] * n时,您正在做的是创建一个计数器,然后让列表中的每个元素都指向该计数器。您创建n计数器,您只需创建一个。

这是因为在Python中,所有内容都是通过引用存储的(更多信息here)。您基本上重复了对计数器对象n次的引用,而不是计数器本身。

这意味着执行cnt[i] += Counter(x)将修改基础计数器,使其看起来像整个列表一样。

要解决此问题,请尝试执行以下操作:

cnt = [Counter() for i in range(n)]

现在,您真正创建了n个不同的计数器(因为您调用构造函数n次)并且会得到预期的行为。