2015-07-23 9 views
5

Sto scrivendo una classe di raccolta Java che deve essere utilizzata con Jython. Voglio gli utenti finali siano in grado di manipolare la raccolta in questo modo:Sovraccarico istanza [chiave] + = val

myCollection = MyJavaCollection() 
myCollection[0] += 10.; 
a = myCollection[0]; //a = 10 
myCollection[0] += 20.; 
b = myCollection[0]; //b = 20 

Ciò che trovo nella documentazione Python è i seguenti metodi:

  • __getitem__ e __setitem__ metodi dovrebbero fare il lavoro per staffa sovraccarico dell'operatore.

  • __iadd__ metodo è il buon candidato per il +=.

Come posso mescolare entrambi per fare voglio quello che voglio?

+0

Cosa deve fare questo codice? Gli insiemi sono inattuabili e non possono essere usati in questo modo, e anche se tu intendi che 'myCollection' è un elenco contenente solo un set di 2 elementi, non riesco a capire come intendi che si occupi di questa operazione. –

+0

ha modificato l'esempio per spiegare i risultati che mi aspetto. Rimosso l'indice come lista e sostituito da un semplice int. – David

+0

Grazie, editori. Questa è una bella domanda ora! –

risposta

6

Nota che myCollection[0] += 10.; sarà davvero essere interpretato qualcosa di simile:

myCollection.__setitem__(0, myCollection.__getitem__(0).__iadd__(10.)) 

Pertanto, per fare questo lavoro è necessario implementare:

  • __getitem__ e __setitem__ su MyJavaCollection; e
  • __iadd__ (o __add__, che Python cadrà di nuovo a se __iadd__ non è implementato) su qualunque .__getitem__ sta per tornare, non MyJavaCollection sé - se tornerà qualcosa che implementa già Inoltre, come i float s nel tuo esempio, stai bene.

una rapida dimostrazione:

>>> class Container(object): 

    def __init__(self, contained): 
     self.contained = contained 

    def __getitem__(self, key): 
     print "Container.__getitem__" 
     return self.contained 

    def __setitem__(self, key, val): 
     print "Container.__setitem__" 
     self.contained = val 


>>> class Contained(object): 

    def __add__(self, other): 
     print "Contained.__add__" 
     return "foo" 


>>> test = Container(Contained()) 
>>> test[0] += 1 
Container.__getitem__ 
Contained.__add__ 
Container.__setitem__ 
>>> test.contained 
'foo' 
+1

Piccola appendice, python proverà ancora a invocare 'Contiene .__ iadd__', ricorrendo solo a' Contenuto .__ add__' se '__iadd__' non era presente. In questo modo se un 'Contenitore' ha una lista allora la lista verrebbe mutata all'interno invece di una nuova lista creata. – Dunes

+0

@Dunes buon punto; editing, grazie – jonrsharpe

+0

bel trucco! Grazie ! – David

2

tua domanda iniziale aveva una lista passata come l'indice, così ho scritto questo assumendo che si voleva accedere all'elemento esimo (i, j) di una lista 2D. È possibile farlo definendo la classe con qualcosa di simile:

class MyJavaCollection: 
    def __init__(self, values): 
     self.values = values 

    def __getitem__(self, indices): 
     """ 
     Returns the item at index (i, j) given an index list [i, j]. 
     """ 
     return self.values[indices[0]][indices[1]] 

    def __setitem__(self, indices, value): 
     """ 
     Sets the (i, j)th item to the input value given an input 
     index list [i, j]. 
     """ 
     self.values[indices[0]][indices[1]] = value 

Qui si sono sovraccaricare il __getitem__ e __setitem__ metodi per recuperare o impostare l'elemento esimo (i, j) nella vostra lista values quando si passa un elenco di indici [i, j]. Se i valori sono solo numeri, la sintassi myCollection([1, 1]) += 10 aggiunge 10 a values[1][1].

Come indicato in un'altra risposta, se non si è semplicemente memorizzare i numeri nel vostro oggetto, quindi potrebbe essere necessario sovrascrivere il metodo __add__ o __iadd__ su qualsiasi classe di tuo dati comprende per ottenere il comportamento desiderato.

Testare il mio esempio di classe:

>> my_list = [[1, 2, 3], [4, 5, 6]] 
>> my_list[1][1] 
    5 
>> my_collect = MyJavaCollection(my_list) 
>> my_collect[[1, 1]] 
    5 
>> my_collect[[1, 1]] += 5 
>> my_collect[[1, 1]] 
    10 

Il documentation on special method names ti dà tutto quello che si può desiderare di conoscere metodi speciali come questo. Può essere un buon posto per cercare se non sei sicuro di quale metodo potresti dover sovraccaricare.