Важливим моментом є те, що осмислення списку створює новий список. Генератор створює ітерабельний об'єкт, який буде "фільтрувати" вихідний матеріал під час руху, коли ви споживаєте біти.
Уявіть, що у вас є файл журналу 2 ТБ під назвою "величезний файл.txt", і ви хочете, щоб вміст і довжина для всіх рядків, що починаються з слова "ВПІТИ".
Тож ви спробуйте почати, написавши список розуміння:
logfile = open("hugefile.txt","r")
entry_lines = [(line,len(line)) for line in logfile if line.startswith("ENTRY")]
Це розбиває весь файл, обробляє кожен рядок і зберігає відповідні рядки у вашому масиві. Отже, цей масив може містити до 2 ТБ вмісту. Це багато оперативної пам’яті і, мабуть, не практичне для ваших цілей.
Тож замість цього ми можемо використовувати генератор, щоб застосувати "фільтр" до нашого вмісту. Жодні дані насправді не читаються, поки ми не почнемо повторювати результат.
logfile = open("hugefile.txt","r")
entry_lines = ((line,len(line)) for line in logfile if line.startswith("ENTRY"))
З нашого файлу ще не було прочитано жодного рядка. Насправді, скажімо, ми хочемо ще більше відфільтрувати результат:
long_entries = ((line,length) for (line,length) in entry_lines if length > 80)
Все ще нічого не було прочитано, але ми зараз вказали два генератори, які діятимуть на наші дані так, як ми хочемо.
Давайте випишемо наші відфільтровані рядки в інший файл:
outfile = open("filtered.txt","a")
for entry,length in long_entries:
outfile.write(entry)
Тепер ми читаємо вхідний файл. Оскільки наш for
цикл продовжує запитувати додаткові лінії, long_entries
генератор вимагає від entry_lines
генератора рядків , повертаючи лише ті, довжина яких перевищує 80 символів. А в свою чергу entry_lines
генератор запитує рядки (відфільтровані так, як зазначено) від logfile
ітератора, який у свою чергу зчитує файл.
Тож замість того, щоб "підштовхувати" дані до своєї функції виводу у вигляді повноцінно заповненого списку, ви надаєте вихідній функції спосіб "тягнути" дані лише тоді, коли це потрібно. Це в нашому випадку набагато ефективніше, але не настільки гнучко. Генератори - це один шлях, один прохід; дані з прочитаного файлу журналу негайно видаляються, тому ми не можемо повернутися до попереднього рядка. З іншого боку, нам не потрібно турбуватися про збереження даних, коли ми закінчимо їх.
[exp for x in iter]
бути просто цукорlist((exp for x in iter))
? чи є різниця у виконанні?