2010-12-07 12 views
14

i lief in etwas Interessantes über die Python Augmented Zuordnung +=Python Augmented Zuordnung Ausgabe

es scheint, automatischer Datentyp zu sein Umwandlung nicht immer für a += b getan wird, wenn ein ein ‚einfacher‘ Datentyp ist, während a = a + b scheint immer

Fällen arbeiten, wo die Umwandlung

a = 1 
b = 1j 

a = 1 
b = 0.5 

Fall erfolgt, bei der Umwandlung nicht

erfolgt
from numpy import array 
a = array([0, 0 ,0]) 
b = array([0, 0, 1j]) 

nach a += b, a bleibt als Integer-Matrix, statt komplexe Matrix

Früher dachte ich, a += b die gleiche wie a = a + b ist, was ist der Unterschied von ihnen in der zugrunde liegenden Implementierung ist?

+0

Worauf bezieht sich 'Array' in Ihrem Beispiel? Ist das vom eingebauten 'Array' Modul? Wenn ja, funktioniert Ihr Beispiel nicht einmal, da es keinen Typcode gibt ... – SingleNegationElimination

+0

'a = Array ([0, 0, 0])' und 'b = Array ([0, 0, 1j])' don ' t Arbeiten Sie mit der Klasse 'array' im gleichnamigen Modul. Ihnen fehlt ein anfänglicher Typcode-Argument. Und, AFAIK, unterstützt die Klasse keine komplexen Zahlen oder '+ =' augmentierte Zuweisung. Also verstehe ich nicht, was Sie hier fragen. – martineau

+0

@martineau Siehe meinen Kommentar zu Rafes Antwort (jetzt gelöscht.) Mit Bezug auf diese NumPy Frage: http://www.scipy.org/FAQ#head-1ed851e9aff803d41d3cded8657b2b15a888ebd5 – ACoolie

Antwort

15

Für die + Operator definiert drei Python "speziellen" Methoden, die ein Objekt implementieren:

  • __add__: zwei Elemente (+ operator) hinzufügt. Wenn Sie a + b tun, wird die __add__ Methode von a mit b als Argument aufgerufen.
  • __radd__: reflektiert hinzufügen; Für a + b wird die __radd__ Methode von b mit a als eine Instanz aufgerufen. Dies wird nur verwendet, wenn a nicht weiß, wie das Addieren durchgeführt wird, und die beiden Objekte unterschiedliche Typen sind.
  • __iadd__: direkt hinzufügen; Wird für a += b verwendet, wobei das Ergebnis der linken Variablen zugewiesen wird. Dies wird separat bereitgestellt, da es möglich sein könnte, es auf eine effizientere Weise zu implementieren. Wenn zum Beispiel a eine Liste ist, dann ist a += b dasselbe wie a.extend(b). Im Fall von c = a + b müssen Sie jedoch eine Kopie von a erstellen, bevor Sie es erweitern, da a in diesem Fall nicht geändert werden soll. Wenn Sie __iadd__ nicht implementieren, wird Python stattdessen nur __add__ aufrufen.

So, da diese verschiedenen Operationen mit separaten Methoden implementiert werden, ist es möglich (aber in der Regel schlechte Praxis), um sie zu implementieren, so dass sie ganz andere Dinge zu tun, oder vielleicht in diesem Fall nur leicht verschiedene Dinge.

Andere haben abgeleitet, dass Sie NumPy verwenden und sein Verhalten erklärt. Sie haben jedoch nach der zugrunde liegenden Implementierung gefragt. Hoffentlich sehen Sie jetzt warum ist es manchmal der Fall, a += b ist nicht das gleiche wie a = a + b. Übrigens kann ein ähnliches Trio von Methoden auch für andere Operationen implementiert werden. Eine Liste aller unterstützten In-Place-Methoden finden Sie unter this page.

+1

Ich sollte beachten, dass in dem Beispiel, das ich für Listen angegeben habe, 'a + = b 'tatsächlich unterschiedliche Ergebnisse von' a = a + b 'hat. Wenn "a" unter einem anderen Namen bekannt ist, "sieht" dieser andere Name die erweiterte Liste nach "a + = b", aber nicht nach "a = a + b". – kindall

0

Rafe Kettlers Antwort ist korrekt, aber es scheint, dass Sie es geschafft haben, a = [0,0,0] zu bekommen, nachdem Sie es zu b hinzugefügt haben (laut Ihrem Post).

Nun, wenn Sie verwenden numpy oder scipy (ich sage das, weil ich array sehen und sich fragen, was Array erstellt hier wird), dann ist diese „normal“ ist, und sollte auch eine Warnung erhöhen:

ComplexWarning: Gießen komplexe Werte an den realen verwirft den Imaginärteil

1

der Unterschied zwischen a = a + b und a += b ist, daß dieser Zusatz wird, wann immer möglich, „in-place“ durchgeführt, die durch Änderung des a Objekts bedeutet. Sie können dies leicht mit Listen sehen.

a = b = [1, 2] 
a += [3] 
print b # [1, 2, 3] 
a = b = [1, 2] 
a = a + [3] 
print b # [1, 2] 
+0

Ja, und im Falle von numply Arrays bedeutet das, dass der Typ von "a" gleich bleibt, so dass komplexe Zahlen nicht dargestellt werden. – tkerwin

7

Wenn array ist numpy.array (Sie eigentlich gar nicht angeben), dann ist das Problem, das passiert, ist, weil diese Arrays nicht ihre Art verändern kann. Wenn Sie das Array ohne einen Typspezifizierer erstellen, wird ein Typ vermutet. Wenn Sie dann versuchen, eine Operation auszuführen, die dieser Typ nicht unterstützt (z. B. Hinzufügen zu einem Typ mit einer größeren Domäne, wie komplex), kann numpy die Berechnung ausführen, weiß aber auch, dass das Ergebnis nur im Typ gespeichert werden kann mit der größeren Domain. Es beklagt sich (auf meiner Maschine, jedenfalls, das erste Mal, dass ich eine solche Aufgabe mache), dass das Ergebnis nicht passt. Bei einer regulären Addition muss in jedem Fall ein neues Array erstellt werden, und numpy gibt den richtigen Typ an.

>>> a=numpy.array([1]) 
>>> a.dtype 
dtype('int32') 
>>> b=numpy.array([1+1j]) 
>>> b.dtype 
dtype('complex128') 
>>> a+b 
array([ 2.+1.j]) 
>>> (a+b).dtype 
dtype('complex128') 
>>> a+=b 
>>> a 
array([2]) 
>>> a.dtype 
dtype('int32') 
>>>