web-dev-qa-db-fra.com

Python: fonction next ()

J'apprends Python à partir d'un livre et je suis tombé sur cet exemple:

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

G = (sum(row) for row in M) # create a generator of row sums
next(G) # Run the iteration protocol

Étant donné que je suis un débutant absolu et que l'auteur n'a fourni aucune explication de l'exemple ou de la fonction next (), je ne comprends pas ce que fait le code.

39
3zzy

L'expression (sum(row) for row in M) crée ce qu'on appelle un générateur. Ce générateur évaluera l'expression (sum(row)) une fois pour chaque ligne dans M. Cependant, le générateur ne fait encore rien, nous venons de le configurer.

L'instruction next(G) est en fait s'exécute le générateur sur M. Donc, si vous exécutez next(G) une fois, vous obtiendrez la somme de la première ligne. Si vous l'exécutez à nouveau, vous obtiendrez la somme de la deuxième ligne, etc.

>>> M = [[1,2,3],
...      [4,5,6],
...      [7,8,9]]
>>> 
>>> G = (sum(row) for row in M) # create a generator of row sums
>>> next(G) # Run the iteration protocol
6
>>> next(G)
15
>>> next(G)
24

Voir également:

68
jtbandes

Si vous en êtes arrivé là, alors vous devriez déjà savoir comment fonctionne une déclaration for-in courante.

La déclaration suivante:

for row in M: print row

verrait M comme une séquence de 3 lignes (sous-séquences) composées de 3 éléments chacune, et itérerait à travers M en affichant chaque ligne sur la matrice:

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

Tu le savais bien ...

Vous pouvez voir les générateurs comme du sucre syntaxique autour des boucles for-in . Oubliez l'appel sum (), et tapez quelque chose comme ceci sur IDLE:

G = (row for row in M)
print G
for a in G: print a

Vous voyez, le générateur ne peut pas être directement représenté sous forme de texte, pas simplement comme une séquence peut l'être . Mais vous pouvez effectuer une itération via un générateur comme s'il s'agissait d'une séquence.

Vous constaterez donc de grandes différences, mais le principe de base est que vous pouvez utiliser un générateur pour ne pas renvoyer uniquement la valeur de chaque élément de la séquence, mais le résultat de toute expression. Dans l'exemple du tutoriel, l'expression est sum (row).

Essayez ce qui suit et voyez ce qui se passe:

G = ("("+str(row[2])+";"+str(row[1])+";"+str(row[0])+")" for row in M)
G.next()
G.next()
G.next()
10
Simón

Pour comprendre comment fonctionne ce code, vous devez comprendre:

1) objet itérable?

2) itérateur?

3) protocole d'itération

4) générateur?

5) Comment fonctionne le générateur?

Laissez-moi vous donner un aperçu de chacun de ceux-ci:

Iterable: un objet itérable est un objet de Python qui a une méthode définie iter ou getitem qui renvoie un itérateur ou peut prendre des index.Essayez un objet sur lequel vous pouvez exécuter loop .. .par exemple:

>>> for i in [1,2,3]:
print(i)

1 2 3

ici, nous avons la liste en tant qu’objet itérable, dont les éléments peuvent être indexés et récupérés à l’aide d’index.

>>> for i in {x:1,y:2}:
print(x)

x y

nous avons ici le dictionnaire comme objet itérable, il boucle sur ses clés. 

Iterator: un itérateur est un objet de Python pour lequel une méthode next (Python2) ou next est définie. C'est tout. C’est un itérateur.

Protocole d'itération: la fonction intégrée iter prend un objet itérable et retourne un itérateur.

>>> x = iter([1, 2, 3])
>>> x
<listiterator object at 0x1004ca850>
>>> x.next()
1
>>> x.next()
2
>>> x.next()
3
>>> x.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration

Generator: les générateurs sont des itérateurs, mais vous ne pouvez les parcourir qu'une seule fois. C’est parce qu’ils ne stockent pas toutes les valeurs en mémoire, ils les génèrent à la volée.

pour par exemple:

def yrange(n):
i = 0
while i < n:
    yield i
    i += 1

Chaque fois que l'instruction de rendement est exécutée, la fonction génère une nouvelle valeur.

>>> y = yrange(3)
>>> y
<generator object yrange at 0x401f30>
>>> y.next()
0
>>> y.next()
1
>>> y.next()
2
>>> y.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration

Donc, un générateur est aussi un itérateur. 

Remarque: chaque fois que next () est appelé, il reprend là où il s'était arrêté (il se souvient de toutes les valeurs de données et de la dernière instruction exécutée) . .

Comprenons ceci avec un exemple:

>>> def foo():
     print "begin"
     for i in range(3):
         print "before yield", i
         yield i
         print "after yield", i
         print "end"

>>> f = foo()
>>> f.next()
begin
before yield 0
0
>>> f.next()
after yield 0
before yield 1
1
>>> f.next()
after yield 1
before yield 2
2
>>> f.next()
after yield 2
end
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration

Venons maintenant à ton problème:

M = [[1,2,3],       #M is iterable object 
 [4,5,6],
 [7,8,9]]

G = (sum(row) for row in M) # creates a generator of row sums 
next(G) # Run the iteration protocol
0
Preeti Duhan