J'ai vu qu'il y a en fait deux (peut-être plus) façons de concaténer des listes en Python: Une façon est d'utiliser la méthode extend ():
a = [1, 2]
b = [2, 3]
b.extend(a)
l'autre pour utiliser l'opérateur plus (+):
b += a
Maintenant, je me demande: Laquelle de ces deux options est la façon `` pythonique '' de faire la concaténation de liste et y a-t-il une différence entre les deux (j'ai consulté le didacticiel Python officiel mais je n'ai rien trouvé sur ce sujet).
.__iadd__()
/.__add__()
/.__radd__()
versus.extend()
Réponses:
La seule différence au niveau du bytecode est que le
.extend
chemin implique un appel de fonction, qui est légèrement plus cher en Python que leINPLACE_ADD
.Ce n'est vraiment rien dont vous devriez vous inquiéter, sauf si vous effectuez cette opération des milliards de fois. Il est cependant probable que le goulot d'étranglement se situerait ailleurs.
la source
.__iadd__()
/.__add__()
/.__radd__()
contre.extend()
Vous ne pouvez pas utiliser + = pour une variable non locale (variable qui n'est pas locale pour la fonction et non globale)
C'est parce que pour le compilateur de cas d' extension, la variable sera chargée en
l
utilisant l'LOAD_DEREF
instruction, mais pour + = il utiliseraLOAD_FAST
- et vous obtenez*UnboundLocalError: local variable 'l' referenced before assignment*
la source
Vous pouvez chaîner des appels de fonction, mais vous ne pouvez pas + = un appel de fonction directement:
la source
Je dirais qu'il y a une différence en ce qui concerne numpy (je viens de voir que la question demande de concaténer deux listes, pas un tableau numpy, mais comme cela pourrait être un problème pour les débutants, comme moi, j'espère que cela peut aider quelqu'un qui cherchent la solution à ce post), par ex.
il reviendra avec erreur
ValueError: les opérandes n'ont pas pu être diffusés avec les formes (0,) (4,4,4)
b.extend(a)
fonctionne parfaitementla source
Du code source de CPython 3.5.2 : Pas de grande différence.
la source
extend () fonctionne avec n'importe quel itérable *, + = fonctionne avec certains mais peut devenir funky.
Python 3.6
* assez sûr .extend () fonctionne avec n'importe quel itérable mais veuillez commenter si je me trompe
la source
list.extend(iterable) Extend the list by appending all the items from the iterable. Equivalent to a[len(a):] = iterable.
Je suppose que j'ai répondu à mon propre astérisque.+=
opérateur avec des objets de types différents (contrairement à deux listes, comme dans la question), vous ne pouvez pas vous attendre à obtenir une concaténation des objets. Et vous ne pouvez pas vous attendre à ce qu'unlist
type soit renvoyé. Jetez un oeil à votre code, vous obtenez unnumpy.ndarray
au lieu delist
.En fait, il existe des différences entre les trois options:
ADD
,INPLACE_ADD
etextend
. Le premier est toujours plus lent, tandis que les deux autres sont à peu près les mêmes.Avec ces informations, je préfère utiliser
extend
, qui est plus rapide queADD
, et me semble plus explicite que ce que vous faitesINPLACE_ADD
.Essayez plusieurs fois le code suivant (pour Python 3):
la source
ADD
avecINPLACE_ADD
etextend()
.ADD
produit une nouvelle liste et y copie les éléments des deux listes originales. Pour sûr, il sera plus lent que le fonctionnement sur place deINPLACE_ADD
etextend()
.Il se trouve que ces informations sont enfouies dans la FAQ de programmation :
Vous pouvez également le constater par vous-même dans le code source CPython: https://github.com/python/cpython/blob/v3.8.2/Objects/listobject.c#L1000-L1011
la source
Selon Python for Data Analysis.
«Notez que la concaténation de liste par addition est une opération relativement coûteuse car une nouvelle liste doit être créée et les objets copiés. Utiliser extend pour ajouter des éléments à une liste existante, en particulier si vous créez une grande liste, est généralement préférable. " Donc,
est plus rapide que l'alternative concaténative:
la source
everything = everything + temp
n'est pas nécessairement implémenté de la même manière queeverything += temp
.everything += temp
est implémenté d'une manière quieverything
n'a pas besoin d'être copiée. Cela rend à peu près votre réponse un point discutable.