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.

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.


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.


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)'

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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.