2012-03-27 1 views
3

Python ne supporte pas l'ajout d'une ligne à une liste:Pourquoi ne puis-je pas ajouter un tuple à une liste avec l'opérateur '+' dans Python?

>>> [1,2,3] + (4,5,6) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: can only concatenate list (not "tuple") to list 

Quels sont les inconvénients pour fournir un tel soutien dans la langue? Notez que je m'attendrais à ce que ce soit symétrique: [1, 2] + (3, 4) et (1, 2) + [3, 4] évalueraient tous les deux une nouvelle liste [1, 2, 3, 4]. Mon raisonnement est qu'une fois que quelqu'un a appliqué l'opérateur + à un mélange de tuples et de listes, ils sont susceptibles de le faire à nouveau (très probablement dans la même expression), donc nous pourrions aussi fournir la liste pour éviter les conversions supplémentaires.

Voici ma motivation pour cette question.

Il arrive assez souvent que j'ai de petites collections que je préfère stocker sous forme de tuples pour éviter toute modification accidentelle et pour améliorer les performances. J'ai alors besoin de combiner ces tuples avec des listes, et d'avoir à convertir chacun d'entre eux en listes rend le code très moche. Notez que += ou extend peuvent fonctionner dans des cas simples. Mais en général, quand j'ai une expression

columns = default_columns + columns_from_user + calculated_columns 

Je ne sais pas lesquels d'entre eux sont des tuples et qui sont des listes. Donc, soit je dois tout convertir à des listes:

columns = list(default_columns) + list(columns_from_user) + list(calculated_columns) 

Ou utiliser itertools:

columns = list(itertools.chain(default_columns, columns_from_user, calculated_columns)) 

Ces deux solutions sont plus laide qu'une simple somme; et le chain peut aussi être plus lent (puisqu'il doit parcourir les entrées un élément à la fois).

+2

Que diriez-vous simplement d'être cohérent? Utilisez des tuples ou utilisez des listes, mais pas les deux. –

+0

Si cela était supporté, je serais d'accord que ce serait le meilleur comportement, mais je pense que si quelqu'un fait '2 +' abc ', il veut clairement' '2abc' 'alors pourquoi ne pas le permettre, etc. - C'est trop d'interprétation. Explicite est mieux qu'implicite. – agf

+1

Vous pouvez simplement utiliser 'itertools.chain' pour enchaîner vos affaires et n'utilisez jamais' + 'à la place. – hochl

Répondre

10

Ce n'est pas pris en charge car l'opérateur + est censé être symétrique. Quel type de retour vous attendez-vous?Le Python Zen comprend la règle

In the face of ambiguity, refuse the temptation to guess. 

Les œuvres suivantes, bien que:

a = [1, 2, 3] 
a += (4, 5, 6) 

Il n'y a pas d'ambiguïté quel type à utiliser ici.

+0

Je m'attendrais à ce que le retour soit une liste, car une fois que je commencerai à utiliser + opérateur, il est probable que je devrais faire encore. Voir ma mise à jour à la question. – max

+3

@max: Je ne vois pas pourquoi cela devrait toujours retourner une liste. Je suis content que Python jette une erreur dans une telle situation, et je suis confiant que cela ne changera jamais. –

+0

@max: Vous avez demandé * Pourquoi Python ne supporte pas l'ajout d'un tuple à une liste *. À mon humble avis, la réponse de Sven cloue cette question. – MattH

1

Vous pouvez utiliser l'opérateur +=, si cela aide:

>>> x = [1,2,3] 
>>> x += (1,2,3) 
>>> x 
[1, 2, 3, 1, 2, 3] 

Vous pouvez également utiliser le constructeur de liste explicitement, mais comme vous l'avez mentionné, la lisibilité pourrait souffrir:

>>> list((1,2,3)) + list((1,2,3)) 
[1, 2, 3, 1, 2, 3] 
+0

Il le fait si je n'ai qu'un seul tuple ajouter. J'ai souvent plusieurs objets, quelques tuples, quelques listes. – max

+0

Sa question est "pourquoi". – agf

2

Pourquoi python doesn ne supporte pas l'ajout de type différent: la réponse simple est qu'ils sont de différents types, que se passe-t-il si vous essayez d'ajouter un itérable et d'attendre une liste? Je voudrais moi-même retourner un autre itérable. Considérez également ['a','b']+'cd' quelle devrait être la sortie? Considérant explicite est mieux que implicite toutes ces conversions implicites sont interdites.

Pour surmonter cette limitation, utilisez la méthode extend de liste pour ajouter tout itérable, par ex.

l = [1,2,3] 
l.extend((4,5,6)) 

Si vous devez ajouter de nombreuses liste/tuples écrire une fonction

def adder(*iterables): 
    l = [] 
    for i in iterables: 
     l.extend(i) 
    return l 

print adder([1,2,3], (3,4,5), range(6,10)) 

sortie:

[1, 2, 3, 3, 4, 5, 6, 7, 8, 9] 
+1

Il sait comment le faire, il veut savoir pourquoi il ne peut pas le faire avec '+'. – agf

+0

@agf: * "et devoir convertir chacun d'eux en liste rend le code très moche" *. Non, apparemment il ne le fait pas, parce que '.extend()' ne convertira rien. –

+1

@RikPoggi Il veut une expression longue comme '[1] + (2,) + (3,) + [4] + (5,)' pour pouvoir être fait à la fois sans conversion ou 'chaîne' ou quelque chose comme cela sans l'amour de la simplicité. Tout code qui utilise 'extend 'pour faire cela dans une ligne sera plus laid que juste cette expression d'addition. – agf

Questions connexes