Le générateur.next () est-il visible dans Python 3?


247

J'ai un générateur qui génère une série, par exemple:

def triangle_nums():
    '''Generates a series of triangle numbers'''
    tn = 0
    counter = 1
    while True:
        tn += counter
        yield tn
        counter += + 1

En Python 2, je peux faire les appels suivants:

g = triangle_nums()  # get the generator
g.next()             # get the next value

cependant en Python 3 si j'exécute les deux mêmes lignes de code j'obtiens l'erreur suivante:

AttributeError: 'generator' object has no attribute 'next'

mais, la syntaxe de l'itérateur de boucle fonctionne en Python 3

for n in triangle_nums():
    if not exit_cond:
       do_something()...

Je n'ai encore rien trouvé qui explique cette différence de comportement pour Python 3.

Réponses:


406

g.next()a été renommé en g.__next__(). La raison en est la cohérence: les méthodes spéciales comme __init__()et __del__()toutes ont des doubles soulignements (ou "dunder" dans la langue vernaculaire actuelle), et ont .next()été l'une des rares exceptions à cette règle. Cela a été corrigé dans Python 3.0. [*]

Mais au lieu d'appeler g.__next__(), utilisez next(g).

[*] Il existe d'autres attributs spéciaux qui ont obtenu ce correctif; func_name, c'est maintenant __name__, etc.


une idée pourquoi python 2 a évité la convention dunder pour ces méthodes en premier lieu?
— Rick soutient Monica

Ce n'est probablement qu'un oubli.
— Lennart Regebro

Qu'en est-il lorsque vous écrasez __ str __ dans les classes? Cela change-t-il str (obj) ou __str __ (obj)?
— NoName

@NoName Il n'y a rien de tel __str__(obj), donc je ne comprends pas vraiment la question.
— Lennart Regebro

1
@NoName Oui, vous le faites.
— Lennart Regebro

144

Essayer:

next(g)

Consultez ce tableau soigné qui montre les différences de syntaxe entre 2 et 3 en ce qui concerne cela.


1
@MaikuMori J'ai corrigé le lien (en attente de révision par les pairs) (Le site diveintopython3.org semble être en panne. Le site miroir diveintopython3.ep.io est toujours vivant)
— gecco

1
Correction du lien à nouveau. python3porting.com/differences.html est plus complet, btw.
— Lennart Regebro

Y a-t-il une justification pour le passage d'une méthode à une fonction, au-delà g.next()devrait être vraiment g.__next__(), et nous avons besoin d'avoir quelque chose qui n'est pas une méthode stupide avec la fonctionnalité de g.next()?
— TC Proctor

11

Si votre code doit s'exécuter sous Python2 et Python3, utilisez la bibliothèque 2to3 six comme ceci:

import six

six.next(g)  # on PY2K: 'g.next()' and onPY3K: 'next(g)'

18
Cela n'est pas vraiment nécessaire, sauf si vous devez prendre en charge les versions Python antérieures à 2.6. Python 2.6 et 2.7 ont la nextfonction intégrée.
— Mark Dickinson
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.