Overschrijf f [k] + = v voor een klasse

Ik implementeer een Fenwick-boomklas in python.

In principe heb ik een interne lijst en twee methoden, get (sleutel) en verhogen (key, inc) om deze lijst te lezen en bij te werken. Het koppelen van f [5] aan f.get (5) is eenvoudig met __ getitem __ , maar is er een manier om f [ 5] + = 2 betekent f.verhoog (5, 2) ?

Ik vond een relevante discussielijst met berichten die zegt dat het kan alleen als u de resultaten van __ getitem __ verpakt in een proxy-klasse die __ iadd __ implementeert, maar dat is geen optie. Dus ik zal waarschijnlijk moeten accepteren dat ik de toename -methode zal gebruiken, ik dacht dat ik hier zou vragen voor het geval een genie de oplossing heeft.

Ik gebruik overigens python3.2.

3

3 antwoord

Nee, de benadering die je beschreef, is vrijwel de enige optie. Er kunnen kleine variaties zijn, maar er is geen (gezond, tenminste) manier om het feit dat f [5] + = 2 __ getitem __ , dan __ setitem__ en voer het gedeelte + alleen uit voor het opgehaalde object, zonder rekening te houden met de container.

3
toegevoegd
@jedwards: Hij wil f [5] + = 2 als syntactische suiker voor f.verhoog (5, 2) .
toegevoegd de auteur delnan, de bron
@jedwards Bij uw antwoord wordt aangenomen dat verhogen self._some_internal_collection [key] + = value is. Gezien het feit dat OP een Fenwick Tree heeft, betwijfel ik sterk dat het zo is. Lees dit nogmaals zorgvuldig door, en als u tot de conclusie komt dat uw antwoord betrekking heeft op de zaak van OP, licht dan alsjeblieft in.
toegevoegd de auteur delnan, de bron
Ik weet niet zeker of hij geïnteresseerd is in de container voor het gedeelte + = .
toegevoegd de auteur jedwards, de bron
Wat ik bedoelde was als 5 en 2 eigenlijk gewoon gehele getallen zijn, dan is dit eenvoudig genoeg (zie mijn antwoord). Als het objecten zijn, en de + = bewerking op de een of andere manier afhankelijk is van hun container f en niet van de objecten zelf, dan zou het lastig zijn maar nog steeds mogelijk.
toegevoegd de auteur jedwards, de bron
Het spijt me, maar dat is gewoon niet waar. Het gaat er niet vanuit dat - dat is slechts een eenvoudige uitleg over hoe het zou kunnen worden gedaan. In feite is elke willekeurige toewijzing van k naar een waarde mogelijk, niet alleen container [k] . Bijvoorbeeld fh.seek (k * 2); return fh.read (2) retourneert het kth paar bytes uit een bestand. De aanname die ik maak is echter dat hij werkt met gehele getallen voor zowel de waarde van f.get (k) en v - maar zoals ik al zei, zou dat niet zo nodig niet te repareren.
toegevoegd de auteur jedwards, de bron

Misschien ben ik iets aan het missen, maar waarom kan je niet gewoon verhogen op setitem ? bijv.

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]

output:

increasing item 2 by 2
5

is het niet wat je wilt?

0
toegevoegd
@jedwards Ik ga ervan uit dat hij een ingewikkelde code heeft in verhogen en vergroten is de juiste manier om van lijst te veranderen, anders zijn duidelijke getitem en setitem voldoende
toegevoegd de auteur Anurag Uniyal, de bron
@Snago Ik zou het veranderen om te krijgen, en ik denk niet dat er sowieso iets anders is dan een dergelijke verpakking te hebben
toegevoegd de auteur Anurag Uniyal, de bron
Voor een, f [2] = 4 zou verhogen() aanroepen - en hoewel dit zou resulteren in de juiste uitkomst, zou het zeker raar zijn als een eenvoudige opdracht genaamd de "toename" -functie.
toegevoegd de auteur jedwards, de bron
Dit zou kunnen werken (als self._data [key] is vervangen door self.get (sleutel) in __ setitem __ ) maar dat zou in stappen + = minder efficiënt dan het gebruik van verhogen (omdat het ook een get zou moeten doen).
toegevoegd de auteur Snago, de bron

Ik denk dat het afhangt van wat v is en of je de code kunt bewerken die de klasse f definieert:

Voor het geval dat v een geheel getal is en u de code van klasse `f kunt bewerken, is dit zeker mogelijk:

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

Welke wordt weergegeven:

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]

Het is niet nodig om in een proxyklasse te verpakken, het is niet nodig om __ iadd __ te definiëren omdat deze al is gedefinieerd voor gehele getallen. Als u nu met een ander elementstatatype (zoals een aangepast object) werkt, moet u mogelijk __ iadd __ definiëren.

0
toegevoegd
Nee, het bijwerken van de interne lijst is niet zo eenvoudig. verhogen (key, inc) doet meer dan alleen het element bij index sleutel in de interne lijst vergroten met inc .
toegevoegd de auteur Snago, de bron
Btw, __ iadd __ is niet gedefinieerd voor gehele getallen, omdat gehele getallen onveranderlijk zijn, maar __ add __ wordt in plaats daarvan automatisch gebruikt.
toegevoegd de auteur Snago, de bron