2015-07-23 13 views
5

Ich schreibe eine Java-Auflistungsklasse, die mit Jython verwendet werden soll. Ich mag Endanwender in die Lage sein der Sammlung auf diese Weise zu manipulieren:Überladungsinstanz [Schlüssel] + = Wert

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

Was ich in der Python-Dokumentation zu finden, sind die folgenden Methoden:

  • __getitem__ und __setitem__ Methoden sollten den Auftrag für Konsole tun Überladung des Bedieners.

  • __iadd__ Methode ist der gute Kandidat für die +=.

Wie kann ich beide tun, will ich will?

+0

Was soll dieser Code tun? Sets sind nicht hashbar und können nicht auf diese Weise verwendet werden, und selbst wenn Sie meinen, meineCollection ist eine Liste, die nur einen Satz mit zwei Elementen enthält, kann ich nicht verstehen, wie Sie meinen, dass diese Operation abgeschlossen ist. –

+0

bearbeitet das Beispiel, um Ergebnisse zu erklären, die ich erwarte. Der Index wurde als Liste entfernt und durch ein einfaches int ersetzt. – David

+0

Danke, Redakteure. Das ist jetzt eine gut aussehende Frage! –

Antwort

6

Beachten Sie, dass myCollection[0] += 10.; wirklich so etwas wie interpretiert werden:

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

daher diese Arbeit machen müssen Sie implementieren:

  • __getitem__ und __setitem__ auf MyJavaCollection; und
  • __iadd__ (oder __add__, der Python fällt zurück auf, wenn __iadd__ nicht implementiert) auf was .__getitem__ wird zurückzukehren, nicht MyJavaCollection selbst - wenn sie etwas zurück, die bereits zusätzlich implementiert, wie die float s In deinem Beispiel geht es dir gut.

Eine schnelle Demonstration:

>>> 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

Kleines Addendum, Python versucht weiterhin, 'Contained .__ iadd__' aufzurufen, wobei nur 'Contained .__ add__' verwendet wird, wenn' __iaddd' nicht vorhanden ist. Auf diese Weise würde, wenn ein "Container" eine Liste hätte, die Liste an Ort und Stelle mutiert anstatt eine neue Liste zu erstellen. – Dunes

+0

@Dunes guter Punkt; Bearbeitung, danke – jonrsharpe

+0

wirklich schöner Trick! Vielen Dank ! – David

2

Ihre ursprüngliche Frage hatte eine Liste als Index übergeben, so schrieb ich dies unter der Annahme, dass Sie das (i, j) te Element einer 2D-Liste zugreifen wollte. Sie können das tun, indem Sie Ihre Klasse mit so etwas wie definieren:

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 

Hier werden Sie eine Überlastung der __getitem__ und __setitem__ Methoden, um das (i, j) te Element in Ihrer values Liste abrufen oder einstellen, wenn Sie eine Liste des Indizes [i, j] passieren. Wenn Ihre Werte nur Zahlen sind, fügt die Syntax myCollection([1, 1]) += 1010 zu values[1][1] hinzu. Wenn Sie in Ihrem Objekt nicht einfach Zahlen speichern, müssen Sie möglicherweise die Methode __add__ oder __iadd__ überschreiben, unabhängig davon, in welcher Klasse Ihre Daten enthalten sind, um das gewünschte Verhalten zu erhalten.

Testen meine Beispielklasse:

>> 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 

Die documentation on special method names gibt Ihnen alles, was Sie so wissen, über spezielle Methoden wünschen kann. Es kann ein guter Ort zum Suchen sein, wenn Sie nicht sicher sind, welche Methode Sie möglicherweise überladen müssen.