Đối số thứ nhất nhận 0 hoặc nhiều đối số, mỗi đối số lặp lại, đối số thứ hai sẽ nhận một đối số được dự kiến sẽ tạo ra các đối tượng lặp:
itertools.chain(list1, list2, list3) iterables = [list1, list2, list3] itertools.chain.from_iterable(iterables)nhưng iterables có thể là bất kỳ trình lặp nào mang lại các lần lặp.
def generate_iterables(): for i in range(10): yield range(i) itertools.chain.from_iterable(generate_iterables())Sử dụng hình thức thứ hai thường là một trường hợp thuận tiện, nhưng vì nó lặp đi lặp lại các lần lặp đầu vào một cách lười biếng, đó cũng là cách duy nhất bạn có thể xâu chuỗi một vô hạn số lượng các trình lặp hữu hạn:
def generate_iterables(): while True: for i in range(5, 10): yield range(i) itertools.chain.from_iterable(generate_iterables())Ví dụ trên sẽ cung cấp cho bạn một lần lặp mang lại mô hình số chu kỳ sẽ không bao giờ dừng, nhưng sẽ không bao giờ tiêu tốn nhiều bộ nhớ hơn so với những gì một cuộc gọi range() yêu cầu.
Họ làm những điều rất giống nhau. Đối với số lượng nhỏ các lần lặp itertools.chain(*iterables) và itertools.chain.from_iterable(iterables) thực hiện tương tự.
Ưu điểm chính của from_iterables nằm ở khả năng xử lý số lượng lặp lớn (có khả năng vô hạn) vì tất cả chúng không cần có sẵn tại thời điểm cuộc gọi.
Một cách khác để xem nó:
chain(iterable1, iterable2, iterable3, ...) dành cho khi bạn đã biết những gì bạn có thể lặp lại, vì vậy bạn có thể viết chúng dưới dạng các đối số được phân tách bằng dấu phẩy.
chain.from_iterable(iterable) dành cho khi các lần lặp của bạn (như iterable1, iterable2, iterable3) được lấy từ một lần lặp khác.
Tôi không thể tìm thấy bất kỳ ví dụ hợp lệ nào ... nơi tôi có thể thấy sự khác biệt giữa chúng [chain và chain.from_iterable] và tại sao phải chọn cái khác
Câu trả lời được chấp nhận là kỹ lưỡng. Đối với những người tìm kiếm một ứng dụng nhanh chóng, hãy xem xét làm phẳng một số danh sách:
list(itertools.chain(["a", "b", "c"], ["d", "e"], ["f"])) # ['a', 'b', 'c', 'd', 'e', 'f']Bạn có thể muốn sử dụng lại các danh sách này sau, vì vậy bạn tạo một danh sách lặp lại:
iterable = (["a", "b", "c"], ["d", "e"], ["f"])Cố gắng
Tuy nhiên, chuyển qua một lần lặp để chain cho kết quả không được làm phẳng:
list(itertools.chain(iterable)) # [['a', 'b', 'c'], ['d', 'e'], ['f']]Tại sao? Bạn đã chuyển vào mục one (một Tuple). chain cần mỗi danh sách riêng biệt.
Các giải pháp
Khi có thể, bạn có thể giải nén một iterable:
list(itertools.chain(*iterable)) # ['a', 'b', 'c', 'd', 'e', 'f'] list(itertools.chain(*iter(iterable))) # ['a', 'b', 'c', 'd', 'e', 'f']Nói chung, sử dụng .from_iterable (vì nó cũng hoạt động với các trình vòng lặp vô hạn):
list(itertools.chain.from_iterable(iterable)) # ['a', 'b', 'c', 'd', 'e', 'f'] g = itertools.chain.from_iterable(itertools.cycle(iterable)) next(g) # "a"