364 votes

Comment initialiser un tableau bidimensionnel en Python ?

Je débute en python et j'essaie d'utiliser une liste à deux dimensions, que je remplis initialement avec la même variable à chaque endroit. J'ai trouvé ceci :

def initialize_twodlist(foo):
    twod_list = []
    new = []
    for i in range (0, 10):
        for j in range (0, 10):
            new.append(foo)
        twod_list.append(new)
        new = []

Il donne le résultat souhaité, mais ressemble à une solution de rechange. Existe-t-il un moyen plus simple, plus court ou plus élégant de procéder ?

11 votes

Juste une petite (ou importante, selon la personne qui regarde) remarque : les listes ne sont pas des tableaux. Si vous voulez des tableaux, utilisez numpy.

0 votes

Cette question est similaire : il traite de l'initialisation des tableaux multidimensionnels en Python.

0 votes

@ArnabDatta Comment initialiser un tableau multidimensionnel dans numpy, alors ?

415voto

Mike Graham Points 22480

Un modèle qui revenait souvent en Python était

bar = []
for item in some_iterable:
    bar.append(SOME EXPRESSION)

ce qui a contribué à motiver l'introduction des compréhensions de listes, qui convertissent ce bout de phrase en

bar = [SOME EXPRESSION for item in some_iterable]

qui est plus court et parfois plus clair. On prend généralement l'habitude de les reconnaître et de remplacer souvent les boucles par des compréhensions.

Votre code suit deux fois ce modèle

twod_list = []                                       \                      
for i in range (0, 10):                               \
    new = []                  \ can be replaced        } this too
    for j in range (0, 10):    } with a list          /
        new.append(foo)       / comprehension        /
    twod_list.append(new)                           /

56 votes

À propos, [[foo]*10 for x in xrange(10)] peut être utilisé pour se débarrasser d'une compréhension. Le problème est que la multiplication fait une copie superficielle, donc new = [foo] * 10 new = [new] * 10 vous donnera une liste contenant la même liste dix fois.

9 votes

De même, [foo] * 10 est une liste avec le même foo 10 fois, ce qui peut être important ou non.

3 votes

Nous pouvons utiliser la chose la plus simple : wtod_list = [[0 for x in xrange(10))] for x in xrange(10)]

272voto

Adam Rosenfield Points 176408

Vous pouvez utiliser un compréhension de la liste :

x = [[foo for i in range(10)] for j in range(10)]
# x is now a 10x10 array of 'foo' (which can depend on i and j if you want)

4 votes

Si la taille (10) est la même, c'est bon, sinon la boucle imbriquée doit venir en premier [foo for j in range(range_of_j)] for i in range(range_of_i)].

6 votes

Cette réponse fonctionne bien mais comme on itère i pour les rangs et j pour les colonnes, je pense qu'il serait préférable d'échanger i et j dans votre syntaxe pour une meilleure compréhension et changez la plage à 2 nombres différents.

153voto

gnibbler Points 103484

Cette méthode est plus rapide que les compréhensions de listes imbriquées

[x[:] for x in [[foo] * 10] * 10]    # for immutable foo!

Voici quelques timings de python3, pour des petites et grandes listes

$python3 -m timeit '[x[:] for x in [[1] * 10] * 10]'
1000000 loops, best of 3: 1.55 usec per loop

$ python3 -m timeit '[[1 for i in range(10)] for j in range(10)]'
100000 loops, best of 3: 6.44 usec per loop

$ python3 -m timeit '[x[:] for x in [[1] * 1000] * 1000]'
100 loops, best of 3: 5.5 msec per loop

$ python3 -m timeit '[[1 for i in range(1000)] for j in range(1000)]'
10 loops, best of 3: 27 msec per loop

Explication :

[[foo]*10]*10 crée une liste du même objet répété 10 fois. Vous ne pouvez pas utiliser cette méthode, car la modification d'un élément modifiera ce même élément dans chaque rangée !

x[:] est équivalent à list(X) mais elle est un peu plus efficace puisqu'elle évite la recherche de noms. Dans tous les cas, elle crée une copie superficielle de chaque ligne, de sorte que tous les éléments sont maintenant indépendants.

Tous les éléments sont les mêmes foo cependant, donc si foo est mutable vous ne pouvez pas utiliser ce schéma, vous devez utiliser le schéma suivant

import copy
[[copy.deepcopy(foo) for x in range(10)] for y in range(10)]

ou supposer une classe (ou une fonction) Foo qui renvoie foo s

[[Foo() for x in range(10)] for y in range(10)]

0 votes

Cela semble beaucoup moins lisible que toutes les autres solutions présentées. Aussi, copy.deepcopy n'est pas fiable et n'est pas quelque chose d'utile très souvent.

4 votes

@Mike, avez-vous manqué la partie en gras ? Si foo est mutable, aucune des autres réponses ne fonctionne (à moins que vous ne mutiez pas du tout foo).

1 votes

Vous ne pouvez pas copier correctement des objets arbitraires en utilisant copy.deepcopy . Vous avez besoin d'un plan spécifique à vos données si vous avez un objet mutable arbitraire.

39voto

[[foo for x in xrange(10)] for y in xrange(10)]

1 votes

Xrange() a été supprimé dans python3.5

1 votes

Pourquoi cela ne fonctionne pas : [0 * col] * ligne. Lorsque je modifie un élément, il se réplique à d'autres endroits. Mais je ne comprends pas pourquoi ?

0 votes

Parce que cela fait exactement la même chose que le code dans la question.

24voto

Mike Graham Points 22480

En général, lorsque vous voulez des tableaux multidimensionnels, vous ne voulez pas une liste de listes, mais plutôt un tableau numpy ou éventuellement un dict.

Par exemple, avec numpy, vous feriez quelque chose comme

import numpy
a = numpy.empty((10, 10))
a.fill(foo)

4 votes

Bien que numpy est génial, mais je pense que c'est un peu trop pour un débutant.

3 votes

Numpy fournit un type de tableau multidimensionnel. Construire un bon tableau multidimensionnel à partir de listes est possible mais moins utile et plus difficile pour un débutant que d'utiliser numpy. Les listes imbriquées sont parfaites pour certaines applications, mais ne sont généralement pas ce que quelqu'un qui veut un tableau à deux dimensions devrait utiliser.

1 votes

Après quelques années de travail occasionnel sur des applications python sérieuses, les bizarreries des tableaux standard de python semblent justifier l'utilisation de numpy . +1

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