Является ли generator.next() видимым в python 3.0?

У меня есть генератор, который генерирует ряд, например:

def triangleNums():
    '''generate series of triangle numbers'''
    tn = 0
    counter = 1
    while(True):
        tn = tn + counter
        yield tn
        counter = counter + 1

в python 2.6 Я могу сделать следующие вызовы:

g = triangleNums() # get the generator
g.next()           # get next val

однако в 3.0, если я выполняю те же две строки кода, я получаю следующую ошибку:

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

но синтаксис цикла итератора работает в версии 3.0

for n in triangleNums():
    if not exitCond:
       doSomething...

Я еще не смог найти ничего, что объясняет эту разницу в поведении для 3.0.

Ответ 1

Правильно, g.next() переименовано в g.__next__(). Причиной этого является постоянство. Специальные методы, такие как __init__() и __del__, имеют двойные символы подчеркивания (или "dunder", поскольку они становятся популярными, чтобы называть их сейчас), а .next() является одним из немногих исключений из этого правила. Python 3.0 исправляет это. [*]

Но вместо вызова g.__next__(), как говорит Паоло, используйте next(g).

[*] Есть более специальные атрибуты, которые получили это исправление, например, атрибуты функции. Больше func_name, теперь он __name__ и т.д.

Ответ 2

Try:

next(g)

Отметьте эту опрятную таблицу, которая показывает различия в синтаксисе между 2 и 3, когда дело доходит до этого.

Ответ 3

Если ваш код должен работать под Python2 и Python3, используйте библиотеку 2to3 six:

import six

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