Mat*_*ner 0 python dictionary variable-assignment
class TrafficData(object):
def __init__(self):
self.__data = {}
def __getitem__(self, epoch):
if not isinstance(epoch, int):
raise TypeError()
return self.__data.setdefault(epoch, ProcessTraffic())
def __iadd__(self, other):
for epoch, traffic in other.iteritems():
# these work
#existing = self[epoch]
#existing += traffic
# this does not
self[epoch] += traffic # here the exception is thrown
return self
Run Code Online (Sandbox Code Playgroud)
在上面修剪过的代码中,我不期望一个项目分配,但显然在标记的行上发生了一个,并抛出以下异常:
File "nethogs2.py", line 130, in __iadd__
self[epoch] += traffic
TypeError: 'TrafficData' object does not support item assignment
Run Code Online (Sandbox Code Playgroud)
但是,如果我改为使用前面两条注释掉的行,则不会抛出任何异常.
在我看来,2应该以相同的方式表现.self[epoch]返回对对象的引用,并通过该对象对其进行修改__iadd__.我在这里误解了什么?我经常在使用词典时遇到这个问题.
值得指出的是,self.__data已经__iadd__定义了值,但没有定义,__add__如果可能的话,我更倾向于修改值.我还想避免创建一个__setitem__方法.
下面是一个演示问题的测试用例,我已经将上面的代码留给了现有的答案.
class Value(object):
def __init__(self, initial=0):
self.a = initial
def __iadd__(self, other):
self.a += other
return self
def __str__(self):
return str(self.a)
class Blah(object):
def __init__(self):
self.__data = {}
def __getitem__(self, key):
return self.__data.setdefault(key, Value())
a = Blah()
b = a[1]
b += 1
print a[1]
a[1] += 2
print a[1]
Run Code Online (Sandbox Code Playgroud)
你到底在做什么:
self[epoch] += traffic
Run Code Online (Sandbox Code Playgroud)
是:
self[epoch] = self[epoch] + traffic
Run Code Online (Sandbox Code Playgroud)
但是你没有定义__setitem__方法,所以你可以自己做.
你还需要:
def __setitem__(self, epoch, value):
self.__data[epoch] = value
Run Code Online (Sandbox Code Playgroud)
或类似的东西.