Чи видно generator.next () в Python 3?


247

У мене є генератор, який генерує серію, наприклад:

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

У Python 2 я можу робити наступні дзвінки:

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

однак у Python 3, якщо я виконую ті самі два рядки коду, я отримую таку помилку:

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

але синтаксис ітератора циклу працює в Python 3

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

Я ще не зміг знайти нічого, що пояснює цю різницю в поведінці для Python 3.

Відповіді:


406

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

Але замість дзвінка g.__next__()використовуйте next(g).

[*] Є інші спеціальні атрибути, які отримали це виправлення; func_name, В даний час __name__, і т.д.


будь-яка ідея, чому python 2 в першу чергу ухилявся від конвенції про дандр для цих методів?
Рік підтримує Моніку

Це, мабуть, лише недогляд.
Леннарт Регебро

Що робити, коли ви перезаписуєте __ str __ у класах? Чи змінює str (obj) або __str __ (obj)?
NoName

@NoName Не існує такого поняття як __str__(obj), тому я не дуже розумію питання.
Леннарт Регебро

1
@NoName Так, так.
Леннарт Регебро

144

Спробуйте:

next(g)

Перегляньте цю акуратну таблицю, яка показує відмінності в синтаксисі між 2 та 3, коли мова йде про це.


1
@MaikuMori Я зафіксував посилання (чекаю на ревізію), (сайт diveintopython3.org, здається, не працює. Дзеркальний сайт diveintopython3.ep.io все ще живий)
gecco

1
Знову виправлено посилання. python3porting.com/differences.html є більш повним, btw.
Леннарт Регебро

Чи є якесь обґрунтування для переходу від методу до функції, за g.next()його межами, насправді повинно бути g.__next__(), і нам потрібно мати щось, що не є методом «дюнда» з функціоналом g.next()?
TC Proctor

11

Якщо ваш код повинен працювати під Python2 та Python3, використовуйте бібліотеку 2to3 шість, як це:

import six

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

18
У цьому немає великої потреби, якщо вам не потрібно підтримувати версії Python раніше, ніж 2.6. Python 2.6 і 2.7 мають nextвбудовану функцію.
Марк Дікінсон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.