2012-06-09 6 views
7

Ist es möglich, [] (__getitem__) Python-Operator- und -Kettenmethoden mit der ursprünglichen Speicherreferenz zu überladen.Überladen [] Python-Operator- und Verkettungsmethoden unter Verwendung einer Speicherreferenz

Imagine habe ich eine Klasse Math, die eine Liste von ganzen Zahlen akzeptiert, wie folgt aus:

class Math(object): 
    def __init__(self, *args, **kwargs): 
     assert(all([isinstance(item, int) for item in list(args)])) 
     self.list = list(args) 

    def add_one(self): 
     for index in range(len(self.list)): 
      self.list[index] += 1 

Und ich möchte etwas tun:

instance = Math(1,2,3,4,5) 
instance[2:4].add_one() 

Nach Ausführen dieses Code instance.list sollte be [1,2,4,5,5], ist das möglich?

Ich weiß, ich könnte etwas wie add_one(2,4) tun, aber das ist nicht der Stil der API, die ich gerne hätte, wenn möglich.

Danke

Antwort

9

Wie Winston erwähnt, müssen Sie ein Hilfsobjekt implementieren:

class Math(object): 
    def __init__(self, *args, **kwargs): 
     self.list = list(args) 

    def __getitem__(self, i): 
     return MathSlice(self, i) 

class MathSlice(object): 
    def __init__(self, math, slice): 
     self.math = math 
     self.slice = slice 

    def add_one(self): 
     for i in xrange(*self.slice.indices(len(self.math.list))): 
      self.math.list[i] += 1 


instance = Math(1,2,3,4,5) 
instance[2:4].add_one() 

print instance.list 

Wie Sie das Mathematik-Objekt mit dem Objekt MathSlice teilen hängt davon ab, was Sie wollen die Semantik, wenn die Mathematik Objektänderungen sein.

+0

'xrange (* self.slice.indices (len (self.math.list)))' fühlt sich schrecklich unpythonisch an. Gibt es einen besseren Weg? – Eric

+0

Sie mischen auch 'self.fields' und' self.list' – Eric

+0

@Eric: Ich entfernte die nicht benötigte Math.add_one, und ja, dass Xrange (* ...) scheint schrecklich umständlich, aber ich weiß es nicht ein kürzerer Weg. –

5

Numpy macht so etwas.

Die __getitem__ Methode erhält ein Objekt slice. Einzelheiten finden Sie unter http://docs.python.org/reference/datamodel.html. Sie müssen ein neues Objekt zurückgeben, dieses Objekt jedoch so implementieren, dass es die ursprüngliche Liste ändert.

+0

Danke Winston für Sie zu beantworten. Ich akzeptiere Neds Antwort, weil er mehr Implementierungsdetails gibt und ich denke, dass andere Benutzer es hilfreicher finden werden. Aber ich schätze Ihre Antwort. – maraujop

Verwandte Themen