3

我在 python 中实现了一个 Fenwick 树类。

基本上我有一个内部列表和两个方法,get(key)以及increase(key, inc),来处理读取和更新这个列表。映射f[5]f.get(5)很容易__getitem__,但是有什么方法可以使f[5] += 2意思f.increase(5, 2)吗?

我发现了一个相关的邮件列表线程__getitem__,它说除非您将结果包装在实现的代理类中,否则无法完成__iadd__,但这不是一个选项。所以我可能不得不接受我必须使用increase- 方法,只是想我会在这里问,以防万一有天才有解决方案。

顺便说一句,我正在使用python3.2。

4

3 回答 3

3

不,您描述的方法几乎是唯一的选择。可能会有细微的变化,但是没有(至少是理智的)方法可以解决f[5] += 2调用__getitem__, then__setitem__+仅在检索到的对象上执行该部分的事实,而不考虑容器。

于 2011-12-06T18:01:55.653 回答
0

可能是我遗漏了一些东西,但你为什么不能直接调用增加setitem?例如

class FTree(object):
    def __init__(self):
        # could be any data structure, on which get and increase work
        self._data = [1,2,3,4] 

    def get(self, key):
        return self._data[key]

    def increase(self, key, value):
        print "increasing item",key,"by",value
        self._data[key] += value

    def __getitem__(self, key):
        return self.get(key)

    def __setitem__(self, key, value):
        self.increase(key, value - self.get(key)


f = FTree()
f[2] += 2
print f[2]

输出:

increasing item 2 by 2
5

这不是你想要的吗?

于 2011-12-06T18:23:36.233 回答
0

我认为这取决于是什么v以及是否可以编辑定义类的代码f

对于 wherev是一个整数的情况,你可以编辑类 `f 的代码,这当然是可能的:

class alist(object):
    def __init__(self):
        self.L = list()

    def append(self, v):
        self.L.append(v)

    def increase(self, k, i):
        self.L[k] += i

    def __getitem__(self, k):
        return self.L[k]

    def __setitem__(self, k, v):
        self.L[k] = v

a = alist()
a.append(8)
a.append(1)
a.append(15)
a.append(57)

print "List contains: ", a.L

print "This should be eight: ", a.get(0)

# Increase using the increase method
a.increase(0,2)

print "This should be ten: ", a.get(0)
print "This should be ten: ", a[0]

# Increment using the [] getitem shortcut
a[0] += 2 

print "This should be twelve: ", a.get(0)
print "This should be twelve: ", a[0]


print "List contains: ", a.L

其中显示:

List contains:  [8, 1, 15, 57]
This should be eight:  8
This should be ten:  10
This should be ten:  10
This should be twelve:  12
This should be twelve:  12
List contains:  [12, 1, 15, 57]

无需包装代理类,无需定义,__iadd__因为它已经为整数定义了。现在,如果您正在使用其他元素数据类型(如自定义对象),您可能需要定义__iadd__.

于 2011-12-06T18:18:33.907 回答