Créer une liste D'un seul élément répété n fois en Python
Je sais qu'une compréhension de liste le fera, mais je me demandais s'il y en avait un encore plus court (et plus pythonique?) approche.
Je veux créer une série de listes, tous de longueur variable. Chaque liste contiendra le même élément e, répété n fois (où n = Longueur de la liste). Comment créer les listes, sans faire
[e for number in xrange(n)]
Pour chaque liste?
6 réponses
Vous pouvez aussi écrire:
[e] * n
Vous devriez noter que si e est par exemple une liste vide, vous obtenez une liste avec n références de la même liste, pas n indépendante vide listes.
Des tests de Performance
À première vue, semble que la répétition est le moyen le plus rapide de créer une liste avec n éléments identiques:
>>> timeit.timeit('itertools.repeat(0, 10)', 'import itertools', number = 1000000)
0.37095273281943264
>>> timeit.timeit('[0] * 10', 'import itertools', number = 1000000)
0.5577236771712819
Mais attendez - ce n'est pas un test juste...
>>> itertools.repeat(0, 10)
repeat(0, 10) # Not a list!!!
La fonction itertools.repeat
ne crée pas réellement la liste, elle crée simplement un objet qui peut être utilisé pour créer une liste si vous le souhaitez! Essayons à nouveau, mais en convertissant en une liste:
>>> timeit.timeit('list(itertools.repeat(0, 10))', 'import itertools', number = 1000000)
1.7508119747063233
Donc, si vous voulez une liste, utilisez [e] * n
. Si vous voulez générer les éléments paresseusement, utiliser repeat
.
>>> [5] * 4
[5, 5, 5, 5]
Soyez prudent lorsque l'élément répété est une liste. La liste ne sera pas clonée: tous les éléments se référeront à la même Liste!
>>> x=[5]
>>> y=[x] * 4
>>> y
[[5], [5], [5], [5]]
>>> y[0][0] = 6
>>> y
[[6], [6], [6], [6]]
Créer une liste D'un seul élément répété n fois en Python
Éléments immuables
Pour les éléments immuables, comme None, strings, tuples ou frozensets, vous pouvez le faire comme ceci:
[e] * 4
Notez que ceci est mieux utilisé uniquement avec des éléments immuables (chaînes, tuples, frozensets, ) dans la liste, car ils pointent tous vers le même élément au même endroit en mémoire. Je l'utilise fréquemment quand je dois construire une table avec un schéma de toutes les chaînes, de sorte que je n'ai pas pour donner à une association.
schema = ['string'] * len(columns)
Éléments mutables
J'utilise Python depuis longtemps, et je n'ai jamais vu de cas d'utilisation où je ferais ce qui précède avec une instance mutable. Au lieu de cela, pour obtenir, disons, une liste vide mutable, un ensemble ou un dict, vous devriez faire quelque chose comme ceci:
list_of_lists = [[] for _ in columns]
Le Trait de soulignement est simplement un nom de variable jetable dans ce contexte.
Si vous avez seulement le numéro, ce serait:
list_of_lists = [[] for _ in range(4)]
Le _
n'est pas vraiment spécial, mais votre vérificateur de style d'environnement de codage se plaindra probablement si vous n'avez pas l'intention d'utiliser la variable et d'utiliser un autre nom.
Mises en garde pour l'utilisation de la méthode immuable avec des éléments mutables:
Méfiez-vous de faire cela avec des objets mutables, lorsque vous changez l'un d'entre eux, ils changent tous parce qu'ils sont tous les même objet:
foo = [[]] *4
foo[0].append('x')
Foo retourne maintenant:
[['x'], ['x'], ['x'], ['x']]
Mais avec des objets immuables, vous pouvez le faire fonctionner car vous modifiez le référence, pas l'objet:
>>> l = [0] * 4
>>> l[0] += 1
>>> l
[1, 0, 0, 0]
>>> l = [frozenset()] * 4
>>> l[0] |= set('abc')
>>> l
[frozenset(['a', 'c', 'b']), frozenset([]), frozenset([]), frozenset([])]
Mais encore une fois, les objets mutables ne sont pas bons pour cela, car les opérations sur place changent l'objet, pas la référence:
l = [set()] * 4
>>> l[0] |= set('abc')
>>> l
[set(['a', 'c', 'b']), set(['a', 'c', 'b']), set(['a', 'c', 'b']), set(['a', 'c', 'b'])]
Itertools a une fonction juste pour cela:
import itertools
it = itertools.repeat(e,n)
Bien sûr, itertools
vous donne un itérateur au lieu d'une liste. [e] * n
Vous donne une liste, mais, en fonction de ce que vous ferez avec ces séquences, la variante itertools
peut être beaucoup plus efficace.
Comme d'autres l'ont souligné, l'utilisation de l'opérateur * pour un objet mutable duplique les références, donc si vous en modifiez une, vous les modifiez toutes. Si vous voulez créer des instances indépendantes d'un objet mutable, votre syntaxe xrange est la façon la plus pythonique de le faire. Si vous êtes dérangé par une variable nommée qui n'est jamais utilisée, Vous pouvez utiliser la variable de soulignement anonyme.
[e for _ in xrange(n)]