Trong Python giao diện của một iterable là một tập con của iterator interface. Điều này có lợi thế là trong nhiều trường hợp, chúng có thể được điều trị theo cách tương tự. Tuy nhiên, có một sự khác biệt quan trọng về ngữ nghĩa giữa hai, vì một đối tượng có thể lặp lại __iter__
trả về một đối tượng trình lặp mới và không chỉ là self
. Làm thế nào tôi có thể kiểm tra rằng một iterable thực sự là một iterable và không phải là một iterator? Về mặt khái niệm, tôi hiểu các vòng lặp có thể là các bộ sưu tập, trong khi một trình vòng lặp chỉ quản lý phép lặp (tức là theo dõi vị trí) nhưng không phải là một bộ sưu tập.Làm thế nào để biết sự khác nhau giữa một trình lặp và một iterable?
Sự khác biệt là ví dụ quan trọng khi muốn lặp lại nhiều lần. Nếu một vòng lặp được đưa ra thì vòng lặp thứ hai sẽ không hoạt động kể từ khi trình vòng lặp đã được sử dụng hết và trực tiếp tăng lên StopIteration
.
Thật hấp dẫn để thử nghiệm phương thức next
, nhưng điều này có vẻ nguy hiểm và không hiểu sao. Tôi có nên kiểm tra xem vòng lặp thứ hai có trống không?
Có cách nào để thực hiện một thử nghiệm như vậy theo một cách thức sâu sắc hơn không? Tôi biết rằng âm thanh này giống như một trường hợp cổ điển của LBYL chống lại EAFP, vì vậy có lẽ tôi nên bỏ cuộc? Hay tôi đang thiếu một cái gì đó?
Edit: S. Lott nói trong câu trả lời của mình bên dưới rằng đây chủ yếu là một vấn đề muốn làm nhiều đi ngang qua iterator, và rằng người ta không nên làm điều này ở nơi đầu tiên. Tuy nhiên, trong trường hợp của tôi dữ liệu là rất lớn và tùy thuộc vào tình hình đã được thông qua nhiều lần để xử lý dữ liệu (có hoàn toàn không có cách nào xung quanh này).
Khả năng lặp lại cũng được cung cấp bởi người dùng và trong trường hợp một lần vượt qua, nó sẽ hoạt động với trình lặp (ví dụ: được tạo bởi trình tạo đơn giản). Nhưng nó sẽ được tốt đẹp để bảo vệ chống lại các trường hợp là một người sử dụng cung cấp chỉ là một iterator khi nhiều vượt qua là cần thiết.
Chỉnh sửa 2: Thực ra đây là ví dụ rất hay cho Abstract Base Classes. Các phương thức __iter__
trong một iterator và một iterable có cùng tên nhưng khác nhau về mặt ngữ nghĩa! Vì vậy, hasattr
là vô ích, nhưng isinstance
cung cấp một giải pháp sạch.
Ồ, đây có vẻ là câu trả lời mà tôi đã tìm kiếm, cảm ơn! Tôi sẽ chờ đợi một chút trước khi chấp nhận nó, trong trường hợp ai đó có thể chỉ ra một vấn đề với điều này. – nikow
Vâng, vấn đề là một cuộc gọi "lãng phí" để obj .__ iter __(), nhưng tôi không thấy cách đáng tin cậy khác để làm điều đó. – vartec
Mặc dù tôi không biết một ví dụ phản đối, điều này không * được bảo đảm * để hoạt động. – tzot