Переопределить f [k] + = v для класса - PullRequest
3 голосов
/ 06 декабря 2011

Я реализую класс дерева Fenwick в python.

В основном у меня есть внутренний список и два метода, get(key) и increase(key, inc), для обработки чтения и обновления этого списка.Сопоставление f[5] с f.get(5) легко с __getitem__, но есть ли способ сделать f[5] += 2 означает f.increase(5, 2)?

Я нашел соответствующую ветку списка рассылки , котораяговорит, что это невозможно сделать, если вы не заключите результаты из __getitem__ в прокси-класс, который реализует __iadd__, но это не вариант.Поэтому мне, вероятно, придется согласиться с тем, что мне придется использовать increase -метод, просто подумал, что я спрошу здесь на случай, если какой-то гений найдет решение.

Я использую python3.2 кстати.

Ответы [ 3 ]

3 голосов
/ 06 декабря 2011

Нет, описанный вами подход - практически единственный вариант.Могут быть небольшие вариации, но нет никакого (нормального, по крайней мере) способа обойти тот факт, что f[5] += 2 вызовет __getitem__, затем __setitem__ и выполнит часть + только для извлеченного объекта, не учитываяконтейнер.

0 голосов
/ 06 декабря 2011

Может быть, я что-то упустил, но почему вы не можете просто позвонить увеличить на 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

это не то, что вы хотите?

0 голосов
/ 06 декабря 2011

Я думаю, это зависит от того, что такое v, и если вы можете редактировать код, определяющий класс f:

Для случая, когда v является целым числом, и вы можете редактировать код класса `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__.

...