Điểm quan trọng là các danh sách hiểu biết tạo ra một danh sách mới. Máy phát tạo ra một đối tượng có thể lặp lại sẽ "lọc" tài liệu nguồn khi bạn sử dụng các bit.
Hãy tưởng tượng bạn có tệp nhật ký 2TB có tên "hugefile.txt" và bạn muốn nội dung và độ dài cho tất cả các dòng bắt đầu bằng từ "ENTRY".
Vì vậy, bạn hãy thử bắt đầu ra bằng cách viết một danh sách hiểu:
logfile = open("hugefile.txt","r")
entry_lines = [(line,len(line)) for line in logfile if line.startswith("ENTRY")]
này slurps lên toàn bộ tập tin, xử lý mỗi dòng, và lưu trữ các dòng tương ứng trong mảng của bạn. Do đó, mảng này có thể chứa tối đa 2TB nội dung. Đó là rất nhiều RAM, và có lẽ không thực tế cho mục đích của bạn.
Vì vậy, thay vào đó, chúng tôi có thể sử dụng trình tạo để áp dụng "bộ lọc" cho nội dung của chúng tôi. Không có dữ liệu nào thực sự được đọc cho đến khi chúng tôi bắt đầu lặp lại kết quả.
logfile = open("hugefile.txt","r")
entry_lines = ((line,len(line)) for line in logfile if line.startswith("ENTRY"))
Thậm chí chưa có một dòng nào được đọc từ tệp của chúng tôi. Trên thực tế, giả sử chúng tôi muốn lọc kết quả của chúng tôi hơn nữa:
long_entries = ((line,length) for (line,length) in entry_lines if length > 80)
Vẫn chưa đọc, nhưng bây giờ chúng tôi đã chỉ định hai máy phát sẽ thực hiện theo dữ liệu của chúng tôi.
Hãy viết ra dòng lọc của chúng tôi vào tập tin khác:
outfile = open("filtered.txt","a")
for entry,length in long_entries:
outfile.write(entry)
Bây giờ chúng ta đọc các tập tin đầu vào. Vì vòng lặp for
của chúng tôi tiếp tục yêu cầu các dòng bổ sung, máy phát điện long_entries
yêu cầu máy phát điện từ máy phát điện entry_lines
, chỉ trả về những người có độ dài lớn hơn 80 ký tự. Và lần lượt, các dòng yêu cầu máy phát điện entry_lines
(được lọc như được chỉ ra) từ trình lặp lặp logfile
, lần lượt đọc tệp.
Vì vậy, thay vì "đẩy" dữ liệu vào hàm đầu ra của bạn dưới dạng danh sách được điền đầy đủ, bạn sẽ cho hàm đầu ra cách "kéo" dữ liệu khi cần. Đây là trường hợp của chúng tôi hiệu quả hơn nhiều, nhưng không hoàn toàn linh hoạt. Máy phát điện là một cách, một đường chuyền; dữ liệu từ tệp nhật ký mà chúng tôi đọc đã bị hủy ngay lập tức, vì vậy chúng tôi không thể quay lại dòng trước đó. Mặt khác, chúng ta không phải lo lắng về việc giữ dữ liệu xung quanh khi chúng ta hoàn thành nó.
có thể '[exp for x in iter]' chỉ là đường cho 'list ((exp for x in iter))'? hoặc là có một sự khác biệt thực hiện? – b0fh
nó nghĩ rằng tôi đã có một câu hỏi có liên quan, vì vậy khi sử dụng năng suất chúng ta có thể sử dụng biểu thức máy phát từ một hàm hoặc chúng ta phải sử dụng năng suất cho một hàm để trả về đối tượng máy phát? –
@ b0fh Câu trả lời rất muộn cho bình luận của bạn: trong Python2 có một sự khác biệt nhỏ, biến vòng lặp sẽ rò rỉ ra khỏi một danh sách hiểu, trong khi một biểu thức máy phát điện sẽ không bị rò rỉ. So sánh 'X = [x ** 2 cho x trong phạm vi (5)]; in x' với 'Y = danh sách (y ** 2 cho y trong phạm vi (5)); in y', thứ hai sẽ đưa ra một lỗi. Trong Python3, việc hiểu danh sách thực sự là đường cú pháp cho biểu thức máy phát được nạp vào 'list()' như bạn mong đợi, vì vậy biến vòng lặp sẽ không còn bị rò rỉ nữa (https://www.python.org/dev/) peps/pep-0289 # chi tiết). –