Apakah generator.next () terlihat di Python 3?

247

Saya memiliki generator yang menghasilkan serangkaian, misalnya:

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

Dengan Python 2 saya dapat melakukan panggilan berikut:

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

Namun dalam Python 3 jika saya menjalankan dua baris kode yang sama saya mendapatkan kesalahan berikut:

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

tetapi, sintaks loop iterator bekerja di Python 3

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

Saya belum dapat menemukan apa pun yang menjelaskan perbedaan perilaku untuk Python 3 ini.

jottos
sumber

Jawaban:

406

g.next()telah diubah namanya menjadi g.__next__(). Alasan untuk ini adalah konsistensi: metode khusus seperti __init__()dan __del__()semua memiliki menggarisbawahi ganda (atau "dunder" dalam bahasa sehari-hari saat ini), dan .next()merupakan salah satu dari sedikit pengecualian untuk aturan itu. Ini diperbaiki dalam Python 3.0. [*]

Tapi alih-alih menelepon g.__next__(), gunakan next(g).

[*] Ada atribut khusus lain yang mendapatkan perbaikan ini; func_name, sekarang __name__, dll.

Lennart Regebro
sumber
ada ide mengapa python 2 menghindari konvensi dunder untuk metode ini?
Rick mendukung Monica
Itu mungkin hanya kekhilafan.
Lennart Regebro
Bagaimana dengan saat Anda menimpa __ str __ di kelas? Apakah itu mengubah str (obj) atau __str __ (obj)?
NoName
@NoName Tidak ada yang namanya __str__(obj), jadi saya tidak begitu mengerti pertanyaannya.
Lennart Regebro
1
@NoName Ya, Anda tahu.
Lennart Regebro
144

Mencoba:

next(g)

Lihat tabel rapi ini yang menunjukkan perbedaan dalam sintaks antara 2 dan 3 ketika sampai pada ini.

Paolo Bergantino
sumber
1
@MaikuMori Saya memperbaiki tautannya (menunggu revisi rekan) (Situs diveintopython3.org tampaknya sedang down. Situs mirror diveintopython3.ep.io masih hidup)
gecco
1
Memperbaiki tautan lagi. python3porting.com/differences.html lebih lengkap, btw.
Lennart Regebro
Apakah ada pembenaran untuk beralih dari suatu metode ke suatu fungsi, di luar g.next()seharusnya benar-benar g.__next__(), dan kita perlu memiliki sesuatu yang bukan metode dunder dengan fungsi g.next()?
TC Proctor
11

Jika kode Anda harus dijalankan di bawah Python2 dan Python3, gunakan pustaka 2to3 enam seperti ini:

import six

six.next(g)  # on PY2K: 'g.next()' and onPY3K: 'next(g)'
danius
sumber
18
Tidak ada banyak kebutuhan untuk ini kecuali Anda perlu mendukung versi Python lebih awal dari 2.6. Python 2.6 dan 2.7 memiliki nextfungsi bawaan.
Mark Dickinson