46 votes

Si x est une liste, pourquoi x + = "ha" fonctionne-t-il, alors que x = x + "ha" lève une exception?

De ce que je sais un peu, + op pour les listes n’exige que le deuxième opérande soit itérable, ce qui est "ha" clairement.

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

31voto

Mark Byers Points 318575

À l'aide de += avec une liste, c'est comme appeler extend, pas +.

  • Vous pouvez appeler extend avec un objet iterable.
  • Vous ne pouvez utiliser qu' + avec une autre liste.

Je ne peux que deviner pourquoi cette décision a été prise, mais j'imagine que c'est pour des raisons de performances. Appelant + résultats dans un nouvel objet qui est créé et tous les articles copiés, alors que extend pouvez utiliser l'espace libre dans la liste existante de l'objet permet d'enregistrer une copie dans certains cas.

Une autre conséquence de cette décision est que si vous écrivez x += y autres références à la liste va voir le changement, mais si vous utilisez x = x + y alors qu'ils ne le seront pas. Cela est démontré ci-dessous:

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

Références

Code source Python pour liste.

Le code Source pour +=:

statique PyObject *
list_inplace_concat(PyListObject *auto, PyObject *autres)
{
 PyObject *résultat;

 résultat = listextend(self, autre);
 if (result == NULL)
 résultat de retour;
Py_DECREF(result);
Py_INCREF(auto);
 retour (PyObject *)auto;
}

Le code Source pour +:

statique PyObject *
list_concat(PyListObject *, PyObject *bb)
{
 Py_ssize_t taille;
 Py_ssize_t i;
 PyObject **src, **dest;
 PyListObject *np;
 if (!PyList_Check(bb)) {
PyErr_Format(PyExc_TypeError,
 "ne peut concaténer liste (pas de \"%.200\") à la liste",
bb->ob_type->tp_name);
 return NULL;
}

 // etc ...

8voto

Chris B. Points 14211

Vous êtes en train de penser à ce sujet à l'envers. Vous vous demandez pourquoi x = x + 'ha' lance une exception, étant donné qu' x += 'ha' travaux. En réalité, la question est pourquoi x += 'ha' travaille à tous.

Tout le monde est d'accord (je l'espère) 'abc' + 'ha' et [1, 2, 3] + ['h', 'a'] devrait fonctionner. Et dans ces cas, la surcharge d' += en place de la modification semble raisonnable.

La langue de créateurs ont décidé qu' [1, 2, 3] + 'ha' ne devrait pas, parce que vous êtes le mixage de différents types. Et qui semble raisonnable.

Donc la question est pourquoi ils ont décidé de permettre le mélange de différents types dans le cas de l' x += 'ha'. Dans ce cas, j'imagine qu'il ya un couple de raisons:

  • C'est un raccourci pratique
  • Il est évident que ce qui se passe (vous ajouter chacun des éléments dans l'objet iterable d' x)

En général, Python essaie de vous laisser faire ce que vous voulez, mais où il y a ambiguïté, il a tendance à vous forcer à être explicite.

5voto

kkaefer Points 493

Lors de la définition des opérateurs, il existe deux opérateurs "add" différents: l'un s'appelle __add__ , l'autre __iadd__ . Le dernier concerne les ajouts sur place avec += , l’autre est l’opérateur régulier + . http://docs.python.org/reference/datamodel.html a plus d'informations à ce sujet.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X