web-dev-qa-db-fra.com

Lignes simples imbriquées pour les boucles

Écrit cette fonction dans python qui transpose une matrice:

def transpose(m):
    height = len(m)
    width = len(m[0])
    return [ [ m[i][j] for i in range(0, height) ] for j in range(0, width) ]

Au cours du processus, j'ai réalisé que je ne comprenais pas vraiment comment une seule ligne imbriquée pour les boucles s'exécutait. Aidez-moi à comprendre en répondant aux questions suivantes:

  1. Quel est l'ordre dans lequel cette boucle for s'exécute?
  2. Si j'avais une boucle triple imbriquée, quel ordre serait-elle exécutée?
  3. Qu'est-ce qui serait égal à l'égalité sans lien pour la boucle?

Donné,

[ function(i,j) for i,j in object ]
  1. Quel type d'objet doit être pour pouvoir utiliser cette structure de boucle?
  2. Quel est l'ordre dans lequel i et j sont affectés aux éléments dans object?
  3. Peut-il être simulé par une structure de boucle for différente?
  4. Cette boucle for peut-elle être imbriquée dans une structure similaire ou différente? Et à quoi cela ressemblerait-il?

Des informations supplémentaires sont également appréciées.

83
Asher Garland

La meilleure source d’information est le tutoriel officiel Python sur la compréhension de la liste . La compréhension des listes est presque identique à celle des boucles for (certes, toute compréhension de liste peut être écrite sous forme de boucle for), mais elles sont souvent plus rapides que d’utiliser une boucle for.

Regardez cette liste plus longue du tutoriel (la partie if filtre la compréhension, seules les parties qui passent l'instruction if sont passées dans la partie finale de la liste (ici (x,y)):)

>>> [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

C'est exactement la même chose que cette boucle for imbriquée (et, comme le dit le tutoriel, notez comment l'ordre de for et de if est le même).

>>> combs = []
>>> for x in [1,2,3]:
...     for y in [3,1,4]:
...         if x != y:
...             combs.append((x, y))
...
>>> combs
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

La différence majeure entre une compréhension de liste et une boucle for est que la partie finale de la boucle for (où vous faites quelque chose) vient au début plutôt que à la fin.

Sur vos questions:

Quel type d'objet doit être pour pouvoir utiliser cette structure de boucle?

Un iterable . Tout objet pouvant générer un ensemble (fini) d’éléments. Ceux-ci incluent tous les conteneurs, listes, ensembles, générateurs, etc.

Quel est l'ordre dans lequel i et j sont affectés aux éléments dans object?

Ils sont affectés dans le même ordre que lorsqu’ils sont générés à partir de chaque liste, comme s’ils se trouvaient dans une boucle for imbriquée (pour votre première compréhension, vous auriez 1 élément pour i, puis chaque valeur de j, 2ème élément dans i, alors chaque valeur de j, etc.)

Peut-il être simulé par une structure de boucle for différente?

Oui, déjà montré ci-dessus.

Cette boucle for peut-elle être imbriquée dans une structure similaire ou différente? Et à quoi cela ressemblerait-il?

Bien sûr, mais ce n'est pas une bonne idée. Ici, par exemple, vous donne une liste de listes de caractères:

[[ch for ch in Word] for Word in ("Apple", "banana", "pear", "the", "hello")]
138
Jeff Tratner

Vous pourriez être intéressé par itertools.product , qui retourne un multiplet itérable contenant des valeurs de tous les itérables que vous lui transmettez. C'est-à-dire que itertools.product(A, B) renvoie toutes les valeurs de la forme _(a, b)_, où les valeurs a proviennent de A et les valeurs b de B. . Par exemple:

_import itertools

A = [50, 60, 70]
B = [0.1, 0.2, 0.3, 0.4]

print [a + b for a, b in itertools.product(A, B)]
_

Cela imprime:

_[50.1, 50.2, 50.3, 50.4, 60.1, 60.2, 60.3, 60.4, 70.1, 70.2, 70.3, 70.4]
_

Notez que l'argument final passé à _itertools.product_ est "intérieur". Généralement, itertools.product(a0, a1, ... an) est égal à [(i0, i1, ... in) for in in an for in-1 in an-1 ... for i0 in a0]

27
Lynn

Tout d'abord, votre premier code n'utilise pas de boucle for en tant que telle, mais un compréhension de la liste .

  1. Serait équivalent à

    pour j dans la plage (0, largeur): pour i dans la plage (0, hauteur): m [i] [j]

  2. De la même manière, il niche généralement comme pour les boucles, de droite à gauche. Mais la syntaxe de compréhension de liste est plus complexe.

  3. Je ne suis pas sûr de ce que cette question demande


  1. Tout objet itérable qui produit des objets itérables qui donnent exactement deux objets (quelle bouchée - c'est-à-dire [(1,2),'ab'] serait valide)

  2. L'ordre dans lequel l'objet cède à l'itération. i va au premier rendement, j au second.

  3. Oui, mais pas aussi jolie. Je crois que cela équivaut fonctionnellement à:

     l = list () 
     pour i, j dans objet: 
     l.append (fonction (i, j)) 
    

    ou même mieux utiliser carte :

    map(function, object)
    

    Mais bien sûr, la fonction devrait avoir i, j elle-même.

  4. N'est-ce pas la même question que 3?

3
korylprince