317 votes

Concaténation de deux listes - différence entre '+=' et extend()

J'ai vu qu'il y avait en fait deux façons (peut-être plus) de concaténer des listes en Python :

L'une des solutions consiste à utiliser la fonction extend() méthode :

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 de la concaténation de listes et y a-t-il une différence entre les deux ? (J'ai consulté le tutoriel officiel de Python mais je n'ai rien trouvé à ce sujet).

1 votes

La différence a peut-être plus d'implications lorsqu'il s'agit de faire du ducktyping et si votre peut-être pas vraiment une liste mais comme une liste soutiens .__iadd__() / .__add__() / .__radd__() par rapport à .extend()

278voto

SilentGhost Points 79627

La seule différence au niveau du bytecode est que l'élément .extend implique un appel de fonction, ce qui est légèrement plus coûteux en Python que l'appel de fonction. INPLACE_ADD .

Il n'y a pas lieu de s'inquiéter, sauf si vous effectuez cette opération des milliards de fois. Il est toutefois probable que le goulot d'étranglement se situe à un autre endroit.

21 votes

La différence a peut-être plus d'implications lorsqu'il s'agit de faire du ducktyping et si votre peut-être pas vraiment une liste mais comme une liste soutiens .__iadd__() / .__add__() / .__radd__() par rapport à .extend()

15 votes

Cette réponse ne mentionne pas les importantes différences de champ d'application.

9 votes

En fait, extends est plus rapide que INPLACE_ADD(), c'est-à-dire la concaténation de listes. gist.github.com/mekarpeles/3408081

225voto

monitorius Points 133

Vous ne pouvez pas utiliser += pour une variable non locale (variable qui n'est pas locale pour la fonction et qui n'est pas non plus globale).

def main():
    l = [1, 2, 3]

    def foo():
        l.extend([4])

    def boo():
        l += [5]

    foo()
    print l
    boo()  # this will fail

main()

C'est parce que pour étendre Dans ce cas, le compilateur chargera la variable l en utilisant LOAD_DEREF mais pour +=, il utilisera LOAD_FAST - et vous obtenez *UnboundLocalError: local variable 'l' referenced before assignment*

6 votes

J'ai des difficultés avec votre explication "variable qui est non local pour la fonction et aussi non globale "Pourriez-vous donner un exemple d'une telle variable ?

9 votes

La variable "l" de mon exemple est exactement de ce type. Elle n'est pas locale pour les fonctions 'foo' et 'boo' (en dehors de leur portée), mais elle n'est pas globale (définie à l'intérieur de la fonction 'main', pas au niveau du module).

3 votes

Je peux confirmer que cette erreur se produit toujours avec python 3.4.2 (vous devrez ajouter des parenthèses pour l'impression mais tout le reste peut rester inchangé).

72voto

isarandi Points 628

Vous pouvez enchaîner des appels de fonction, mais vous ne pouvez pas += un appel de fonction directement :

class A:
    def __init__(self):
        self.listFoo = [1, 2]
        self.listBar = [3, 4]

    def get_list(self, which):
        if which == "Foo":
            return self.listFoo
        return self.listBar

a = A()
other_list = [5, 6]

a.get_list("Foo").extend(other_list)
a.get_list("Foo") += other_list  #SyntaxError: can't assign to function call

10voto

leoluk Points 6039

Selon la Le zen de Python :

La simplicité est préférable à la complexité.

b += a est plus simple que b.extend(a) .

Les modules intégrés sont tellement optimisés qu'il n'y a pas de réelle différence de performance.

9voto

Lance Ruo Zhang Points 158

Je dirais qu'il y a quelques différences avec numpy (je viens de voir que la question portait sur la concaténation de deux listes, et non sur un tableau numpy, mais comme cela peut être un problème pour un débutant comme moi, j'espère que cela pourra aider quelqu'un qui cherche la solution à ce post), par ex.

import numpy as np
a = np.zeros((4,4,4))
b = []
b += a

il renverra l'erreur

ValueError : les opérandes ne peuvent pas être diffusés ensemble avec des formes (0,) (4,4,4)

b.extend(a) fonctionne parfaitement

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