提供的所有代码都在python 3.3中。
我们假设我创建了以下Counter()对象:
>>> from collections import Counter
>>> g = Counter(a=2, b=5, c=6, d = 3)
>>> g
Counter({'a': 2, 'b': 5, 'd': 3, 'c': 6})
我现在可以通过简单地执行类似
的操作来更改计数器中的所有值>>> g['b']=4
然而,我想检测来自Counter的特定值何时更改。当发生这种情况时,我想要执行一个函数,然后从计数器增加另一个特定值(如果它可以直接执行,没有函数 - 让我知道)。
例如,如果' a'递增,' c'并且' d'应该也是。
背景:
我正在编写一种算法,在字符串中搜索具有某些属性的子字符串,将这些子字符串写入列表,然后在子字符串中搜索更细小的子字符串,将它们分配给更高的子字符串。当最终函数计算出这些子串的所有出现时,我不希望它遍历子串的每个层次结构,而只需要递增更高的子串。附加的回调应该增加所有子子串。
由于我无法一次性添加所有回调,使用某种方法将回调添加到运行中的值会很棒。
答案 0 :(得分:0)
正如我在评论中提到的,您需要覆盖__setitem__
,无论是在您创建的Counter的新子类中,还是在您创建的新的从头开始的类中。
但是,您的评论表明您确实要覆盖g['a'] += 1
,这更有问题。除非对象g['a']
(不是g
)定义了自己的__iadd__
方法(整数没有),否则g['a'] += 1
与g['a'] = g['a'] + 1
相同。这意味着g
永远不会看到添加的1;它只会在添加1之后看到新的结果值。换句话说,如果g['a']
为2而您g['a'] += 1
,则g
永远不会看到1;它只看到3(这是在为其当前值加1后得到的)。
如果您想使用“增量”差异进行处理,则必须自行反映。下面是一个简单的示例,其中为字符串键设置新值也会更改其所有单个字符的值,并通过原始键的旧值和新值之间的差值递增它们:
class MagicCounter(collections.Counter):
def __setitem__(self, key, val):
# see how much is being "added"
diff = val - self[key]
super(MagicCounter, self).__setitem__(key, val)
if len(key) > 1:
for item in key:
self[item] += diff
然后:
>>> c = MagicCounter()
>>> c['a'] = 1
>>> c['b'] = 1
>>> c['c'] = 1
>>> c
MagicCounter({'a': 1, 'c': 1, 'b': 1})
>>> c['abc'] += 1
>>> c
MagicCounter({'a': 2, 'c': 2, 'b': 2, 'abc': 1})