2010-07-09 11 views
46

Von dem, was ich weiß, erfordert + op für Listen nur, dass der zweite Operand iterierbar ist, was "ha" eindeutig ist.Wenn x eine Liste ist, warum funktioniert x + = "ha", während x = x + "ha" eine Ausnahme auslöst?

In Code:

>>> x = [] 
>>> x += "ha" 
>>> x 
['h', 'a'] 
>>> x = x + "ha" 
Traceback (most recent call last): 
File "<stdin>", line 1, in <module> 
TypeError: can only concatenate list (not "str") to list 
+1

Ich "stimme" mit Ihrer Frage überein; es ist ein gutes Argument gegen die Überlastung des Operators für mich. – u0b34a0f6ae

+0

Löschte meine Antwort nach dem Bearbeiten - es scheint, Sie wundern sich über den Grund hinter nicht unterstützen + zwischen einer Liste und einem iterable - mein Fehler. Anders als zu sagen: "Ja, warum nicht?", Habe ich keine Antwort. –

+3

das ist ein * Haupt * Bruch. Im Allgemeinen sollte jede Sprache oder Bibliothek, die unterschiedliche Verhaltensweisen für gleich aussehende Operatoren definiert, als benutzerfeindlich betrachtet werden. niemand vernünftig würde '+' für String-Verkettung verwenden: Diese Operation ist nicht kommutativ! –

Antwort

33

Mit += mit einer Liste ist extend wie der Aufruf, nicht +.

  • Sie können extend mit einem iterablen aufrufen.
  • Sie können + nur mit einer anderen Liste verwenden.

Ich kann nur raten, warum diese Entscheidung getroffen wurde, aber ich stelle mir vor es ist aus Leistungsgründen. Der Aufruf + führt dazu, dass ein neues Objekt erstellt wird und alle Objekte kopiert werden, während extend freien Speicherplatz im vorhandenen Listenobjekt verwenden kann und in einigen Fällen eine Kopie speichert.

Ein weiterer Nebeneffekt dieser Entscheidung ist, dass wenn Sie x += y schreiben andere Hinweise auf die Liste die Änderung sehen, aber wenn Sie x = x + y verwenden, dann werden sie nicht. Dies wird im Folgenden gezeigt:

 
>>> x = ['a','b'] 
>>> y = ['c', d'] 
>>> z = x 
>>> x += y 
>>> z 
['a', 'b', 'c', 'd'] 

>>> x = ['a','b'] 
>>> y = ['c', d'] 
>>> z = x 
>>> x = x + y 
>>> z 
['a', 'b'] 

Referenzen

Python source code for list.

Quellcode für +=:

 
static PyObject * 
list_inplace_concat(PyListObject *self, PyObject *other) 
{ 
    PyObject *result; 

    result = listextend(self, other); 
    if (result == NULL) 
     return result; 
    Py_DECREF(result); 
    Py_INCREF(self); 
    return (PyObject *)self; 
} 

Quellcode für +:

 
static PyObject * 
list_concat(PyListObject *a, PyObject *bb) 
{ 
    Py_ssize_t size; 
    Py_ssize_t i; 
    PyObject **src, **dest; 
    PyListObject *np; 
    if (!PyList_Check(bb)) { 
     PyErr_Format(PyExc_TypeError, 
        "can only concatenate list (not \"%.200s\") to list", 
        bb->ob_type->tp_name); 
     return NULL; 
    } 

    // etc ... 
+20

Ich denke, die wirkliche Frage ist hier, "warum solche Inkonsistenz?" – doublep

+0

Ich bin am Rande des Gehens -1 auf diese Antwort, da es die Frage überhaupt nicht beantwortet (siehe @ Doublep Kommentar). –

+5

Ich denke nicht, dass diese Frage eine Kritik des Designs ist. Der erste Schritt muss sein, zu verstehen, wie die Inkonsistenz implementiert wird, und das ist alles, was wir hier helfen können. Die größeren Fragen, die du kommentierst, sind völlig außerhalb des Rahmens von SO, wenn du mich fragst :) –

8

Sie rückwärts darüber nachzudenken. Sie fragen, warum x = x + 'ha' eine Ausnahme auslöst, vorausgesetzt, dass x += 'ha' funktioniert. Wirklich, die Frage ist, warum x += 'ha' überhaupt funktioniert.

Jeder stimmt zu (ich hoffe), dass 'abc' + 'ha' und [1, 2, 3] + ['h', 'a'] sollte funktionieren. Und in diesen Fällen scheint die Überlastung += zu tun, um Änderungen vor Ort zu tun.

Die Sprachdesigner entschieden, dass [1, 2, 3] + 'ha' sollte nicht, weil Sie verschiedene Arten mischen. Und das scheint auch vernünftig.

Also die Frage ist, warum sie beschlossen Mischen verschiedener Typen im Fall von x += 'ha' zu ermöglichen. In diesem Fall stelle ich mir ein paar Gründe gibt es:

  • Es ist ein praktisches Kürzel
  • Es ist offensichtlich, was passiert (Sie hängen Sie jedes der Elemente in der iterable zu x)

Allgemein , Python versucht, dich tun zu lassen, was du willst, aber wo es Unklarheiten gibt, zwingt es dich dazu, explizit zu sein.

+2

ein weiteres vorläufiges -1: für mich ist es offensichtlich, dass 'x + = y 'für jedes' x' und 'y' definiert ist als' x = x + y'. Es ist sofort klar, dass Sie vermieden haben, die Frage zu beantworten. ;) –

+6

Ich denke der Punkt hier ist, dass es * nicht * offensichtlich ist, daher die Frage. In den meisten anderen Programmiersprachen, in denen sowohl '+ =' als auch '+' definiert sind, wird 'x + = y 'normalerweise so definiert, dass es exakt gleich' x = x + y 'ist. In der Tat ist einer der Aliasnamen für den anderen. –

+0

Es ist offensichtlich in dem Sinne, dass, wenn Sie es versuchen, es ist sehr klar, was passiert. Und es ist nicht so, als wenn Sie nicht erwartet hätten, dass es funktioniert, Sie werden enttäuscht sein, wenn es passiert. –

5

Bei der Definition von Operatoren gibt es zwei verschiedene "add" -Operatoren: Einer heißt __add__, der andere __iadd__. Letzterer ist für direkte Ergänzungen mit +=, der andere ist der reguläre Operator +. http://docs.python.org/reference/datamodel.html hat mehr Infos dazu.

Verwandte Themen