代码之家  ›  专栏  ›  技术社区  ›  Matt Joiner

意外的对象分配

  •  0
  • Matt Joiner  · 技术社区  · 15 年前
    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
    

    在上面修剪过的代码中,我不希望进行项分配,但显然有一个项分配发生在标记行上,并引发以下异常:

      File "nethogs2.py", line 130, in __iadd__
        self[epoch] += traffic
    TypeError: 'TrafficData' object does not support item assignment
    

    但是,如果我使用前面2行注释掉的行,则不会引发异常。

    如我所见,这两个应该以同样的方式表现。 self[epoch] 返回对对象的引用,并通过该对象在适当位置进行了修改 __iadd__ . 我在这里误解了什么?我经常在使用字典时遇到这个问题。

    更新0

    可能值得指出的是 self.__data 阿伊达德 已定义,但未定义 __add__ 如果可能的话,我更愿意在适当的地方修改这个值。我还想避免创建 __setitem__ 方法。

    更新1

    下面是一个演示这个问题的测试用例,我将上面的代码留给现有的答案。

    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]
    
    3 回复  |  直到 15 年前
        1
  •  1
  •   Alex Martelli    15 年前

    可能值得指出的是 中的值 self.__data __iadd__ 已定义,但未定义 __add__ 我更愿意修改 尽可能放置。

    在你描述的情况下,为了给以前的答案增加一些精确性, self[epoch] += traffic 准确地翻译为:

    self[epoch] = self[epoch].__iadd__(traffic)
    

    所以如果你想要的只是 阿伊达德 如果没有项目分配部分,则您的选择仅限于您在已发布的代码或调用的代码的注释中已标识的解决方案。 阿伊达德 你自己——可能通过 operator 模块,尽管我相信 operator.__iadd__(self[epoch], traffic) 与简单的相比没有附加值 self[epoch].__iadd__(traffic) (当 self[epoch] 有一个 阿伊达德 方法)。

        2
  •  6
  •   gruszczy    15 年前

    你在做什么:

    self[epoch] += traffic
    

    是:

    self[epoch] = self[epoch] + traffic
    

    但你还没有定义 __setitem__ 方法,这样你就可以自己做了。

    你也需要:

    def __setitem__(self, epoch, value):
            self.__data[epoch] = value
    

    或者类似的东西。

        3
  •  0
  •   Tendayi Mawushe    15 年前

    代码:

    self[epoch] += traffic
    

    句法糖用于:

    self[epoch] = self[epoch] + traffic
    

    所以 分配不是意外的,它是中的分配 += . 因此,您还需要重写 __setitem__() 方法。