Trình tạo.next () có thể nhìn thấy trong Python 3 không?


247

Tôi có một trình tạo tạo một chuỗi, ví dụ:

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

Trong Python 2 tôi có thể thực hiện các cuộc gọi sau:

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

tuy nhiên trong Python 3 nếu tôi thực thi hai dòng mã giống nhau thì tôi gặp lỗi sau:

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

nhưng, cú pháp lặp vòng lặp không hoạt động trong Python 3

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

Tôi chưa thể tìm thấy bất cứ điều gì giải thích sự khác biệt trong hành vi cho Python 3.

Câu trả lời:


406

g.next()đã được đổi tên thành g.__next__(). Lý do cho điều này là tính nhất quán: các phương thức đặc biệt như __init__()__del__()tất cả đều có dấu gạch dưới kép (hoặc "dunder" trong ngôn ngữ hiện tại), và .next()là một trong số ít trường hợp ngoại lệ cho quy tắc đó. Điều này đã được sửa trong Python 3.0. [*]

Nhưng thay vì gọi g.__next__(), hãy sử dụng next(g).

[*] Có những thuộc tính đặc biệt khác đã được sửa chữa này; func_name, là bây giờ __name__, vv


Bất cứ ý tưởng tại sao python 2 đã tránh quy ước dunder cho các phương thức này ngay từ đầu?
Rick hỗ trợ Monica

Đó có lẽ chỉ là một sự giám sát.
Lennart Regebro

Còn khi bạn ghi đè __ str __ trong các lớp thì sao? Nó có thay đổi str (obj) hay __str __ (obj) không?
NoName

@NoName Không có điều gì như __str__(obj)vậy, vì vậy tôi không thực sự hiểu câu hỏi.
Lennart Regebro

1
@ Không Tên Có, bạn làm.
Lennart Regebro

144

Thử:

next(g)

Kiểm tra bảng gọn gàng này cho thấy sự khác biệt về cú pháp giữa 2 và 3 khi nói đến điều này.


1
@MaikuMori Tôi đã sửa liên kết (chờ sửa đổi ngang hàng) (Trang web diveintopython3.org dường như ngừng hoạt động. Trang web nhân bản diveintopython3.ep.io vẫn còn sống)
gecco

1
Đã sửa liên kết một lần nữa. python3porting.com/differences.html hoàn thiện hơn, btw.
Lennart Regebro

Có bất kỳ lời biện minh nào cho việc chuyển đổi từ một phương thức sang một chức năng, g.next()thực sự nên như vậy g.__next__(), và chúng ta cần phải có một cái gì đó không phải là một phương pháp sai lầm với chức năng của g.next()?
TC Proctor

11

Nếu mã của bạn phải chạy trong Python2 và Python3, hãy sử dụng thư viện 6to3 sáu như thế này:

import six

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

18
Không cần nhiều thứ cho điều này trừ khi bạn cần hỗ trợ các phiên bản Python sớm hơn 2.6. Python 2.6 và 2.7 có nextchức năng tích hợp sẵn.
Mark Dickinson
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.