Вирази-генератори. Відмінність між виразом-генератором та генератором списків
Перед вивченням даної теми рекомендується ознайомитись з наступною темою:
Зміст
- 1. Оголошення та використання виразу-генератора. Загальна форма
- 2. Відмінності між генераторами списків та виразами-генераторами
- 3. Приклад, що демонструє відмінність між виразом-генератором та генератором списку
- 4. Приклади використання виразів-генераторів
- 5. Формування послідовності чисел у виразі-генераторі згідно з умовою if . Приклад
- Споріднені теми
Пошук на інших ресурсах:
1. Оголошення та використання виразу-генератора. Загальна форма
Вирази-генератори працюють так само як і функції-генератори. У мові Python вираз-генератор – це конструкція на базі циклу for, яка дозволяє отримати послідовність значень, що будуть постачатись викликаючому коду за вимогою (при необхідності). Синтаксично вирази-генератори подібні до генераторів списків, тільки мають одну відмінність при оголошенні. Вираз-генератор оголошується в круглих дужках ( ) на відміну від генератору списку, який оголошується в квадратних дужках [ ].
Загальна форма оголошення та використання виразу-генератору наступна
IterObj = ( expression for variable in sequence [if condition] )
тут
- IterObj – ітерований об’єкт, що підтримує протокол ітерацій. Такий об’єкт містить перелік значень, які будуть отримуватись у викликаючому коді за вимогою з допомогою методу next();
- expression – вираз, який формує послідовність нових значень;
- variable – змінна-лічильник, яка по-черзі приймає значення з послідовності sequence;
- condition – умовний вираз. Це випадок, коли послідовність значень формується згідно з деякою умовою.
Крім синтаксичної відмінності, вирази-генератори відрізняються від генераторів списків також способом надання послідовності згенерованих значень (дивіться наступний пункт).
⇑
2. Відмінності між генераторами списків та виразами-генераторами
Між виразами-генераторами та генераторами списків існують наступні відмінності:
- генератор списків формується в квадратних дужках [ ]. В свою чергу, вираз-генератор формується в круглих дужках ( );
- генератор списків створює в пам’яті список з результатами, який можна багатократно отримати чи вивести. Вираз-генератор забезпечує створення об’єкту-генератора, який постачає по одному елементу з послідовності. При звертанні до об’єкту-генератора за наступним елементом кожен елемент витягується з набору і вже не розміщується в цьому наборі. Витягування елементу з об’єкту-генератора може здійснюватись в циклі for автоматично або з допомогою виклику методу next().
У порівнянні з генераторами списків, використання виразів-генераторів дає наступні переваги:
- вирази-генератори оптимізують використання пам’яті за рахунок того, що не потрібно зберігати увесь список з результатами;
- ефективність виразів-генераторів зростає зі збільшенням об’ємів результатів, які потрібно видати.
⇑
3. Приклад, що демонструє відмінність між виразом-генератором та генератором списку
Нижченаведений приклад демонструє відмінність між генераторами списків та виразами-генераторами.
# Вирази-генератори та генератори списків. Порівняння # 1. Задати кількість чисел, які потрібно згенерувати n = 8 # 2. Використання виразу-генератора, тут вказуються круглі дужки () # 2.1. Отримати ітерований об'єкт IterObj = ( i+1 for i in range(n) ) print("IterObj = ", IterObj) # 2.2. Конвертувати ітерований об'єкт в список та вивести його L = list(IterObj) print("L = ", L) # L = [1, 2, 3, 4, 5, 6, 7, 8] # 2.3. Повторно отримати значення з ітерованого об'єкту L2 = list(IterObj) print("L2 = ", L2) # L2 = [] - пустий список, всі значення вже витягнуто # 3. Використання генератору списків, тут вказуються квадратні дужки [] # 3.1. Сформувати список ResultList = [ i+1 for i in range(n) ] print("ResultList = ", ResultList) # 3.2. Конвертувати список в інший список L3 = list(ResultList) # L3 = [1, 2, 3, 4, 5, 6, 7, 8] print("L3 = ", L3) # 3.3. Повторно конвертувати список в інший список L4 = list(ResultList) print("L4 = ", L4) # L4 = [1, 2, 3, 4, 5, 6, 7, 8] - список не пустий
Результат виконання програми
IterObj = <generator object <genexpr> at 0x039714F0> L = [1, 2, 3, 4, 5, 6, 7, 8] L2 = [] ResultList = [1, 2, 3, 4, 5, 6, 7, 8] L3 = [1, 2, 3, 4, 5, 6, 7, 8] L4 = [1, 2, 3, 4, 5, 6, 7, 8]
Як видно з результату, вираз-генератор сформував об’єкт IterObj, повторне використання якого дало пустий список L2. Чому пустий список? Тому що всі значення з об’єкту IterObj були вже витягнуті попереднім викликом методу list, в результаті якого було утворено список L.
В свою чергу, генератор списків сформував у пам’яті список з даними, який може багатократно використовуватись без втрати його цілісності.
⇑
4. Приклади використання виразів-генераторів
4.1. Сформувати послідовність та отримати список з ітерованого об’єкту
Найпростіший приклад формування послідовності цілочисельних значень з допомогою виразу-генератора.
# Вирази-генератори # 1. Задати кількість чисел n = int(input("n = ")) # 2. Використання виразу-генератора. # Отримати ітерований об'єкт IterObj = (i+1 for i in range(n)) print("IterObj = ", IterObj) # 3. Конвертувати ітерований об'єкт в список та вивести його L = list(IterObj) print("L = ", L)
Тестовий приклад
n = 8 IterObj = <generator object <genexpr> at 0x03DF19B0> L = [1, 2, 3, 4, 5, 6, 7, 8]
⇑
4.2. Сформувати послідовність з n випадкових чисел та отримати кортеж
У прикладі, спочатку формується ітерований об’єкт що містить n випадкових чисел. Потім цей об’єкт конвертується в кортеж з допомогою методу tuple().
# Вирази-генератори. # 1. Підключити модуль random import random # 2. Задати кількість чисел які потрібно згенерувати n = int(input("n = ")) # 3. Отримати ітерований об'єкт та вивести його IterObj = ( random.randint(1, 100) for i in range(n) ) print("IterObj = ", IterObj) # 4. Конвертувати ітерований об'єкт в кортеж T = tuple(IterObj) # 5. Вивести результат print("T = ", T)
Тестовий приклад
n = 10 IterObj = <generator object <genexpr> at 0x03DD19B0> T = (94, 12, 59, 16, 39, 96, 30, 37, 33, 60)
⇑
4.3. Використання циклу while та методу next() для витягування значень з ітерованого об’єкту
Витягування значень з ітерованого об’єкту відбувається завдяки неявному або явному виклику методу next(). Якщо для витягування значень використовується цикл for, то метод next() викликається неявно (автоматично) і не потрібно реалізовувати явний виклик цього методу. Якщо витягування значень відбувається в циклі while, то тут обов’язково має бути використаний метод next().
Нижченаведений приклад демонструє застосування циклу while для витягування значень з ітерованого об’єкту.
# Вирази-генератори та генератори списків. # 1. Підключити модуль random import random # 2. Задати кількість чисел які потрібно згенерувати n = int(input("n = ")) # 3. Отримати ітерований об'єкт з послідовністю чисел та вивести його IterObj = ( random.randint(1, 100) for i in range(n) ) print("IterObj = ", IterObj) # 4. Цикл витягування значень з ітерованого об'єкту. # Поєднання інструкції while та методу next() i=0 L = [] # результуючий список значень while i<n: # Отримати 1 елемент з ітерованого об'єкту - метод next() item = next(IterObj) # Додати елемент до списку L = L + [item] # Збільшити лічильник ітерацій i = i+1 # 5. Вивести результат print("L = ", L)
Тестовий приклад
n = 8 IterObj = <generator object <genexpr> at 0x040819B0> L = [66, 8, 6, 93, 1, 41, 77, 85]
⇑
4.4. Використання циклу for для ітерованого об’єкту
У цьому прикладі витягування одиночних значень зі згенерованого об’єкту здійснюється циклом for. Метод next() у цьому випадку викликати не потрібно. Цей метод викликається автоматично.
# Вирази-генератори. # 1. Задати рядок з послідовнітю символів s = str(input("s = ")) # 2. Отримати ітерований об'єкт, що містить символи введеного рядка IterObj = ( c for c in s ) # вираз-генератор print("IterObj = ", IterObj) # 3. Цикл витягування значень з ітерованого об'єкту. # Використовується інструкція for для формування списку L. L = [] for c in s: # Тут метод next() викликається неявно (автоматично) L = L + [c] # 4. Вивести результат print("L = ", L)
Тестовий приклад
s = jklmn oprst IterObj = <generator object <genexpr> at 0x03ED19B0> L = ['j', 'k', 'l', 'm', 'n', ' ', 'o', 'p', 'r', 's', 't']
⇑
5. Формування послідовності чисел у виразі-генераторі згідно з умовою if . Приклад
У прикладі, на основі виразу-генератора формується ітерований об’єкт IterObj, що містить послідовність цілих випадкових парних чисел з заданого діапазону.
# Вирази-генератори # 1. Підключити модуль random import random # 2. Ввести n n = int(input("n = ")) # 3. Ввести діапазон можливих значень цілих чисел [a; b] a = int(input("a = ")) b = int(input("b = ")) # 4. Сформувати список з набором випадкових чисел, # використовується генератор списків numbers = [ random.randint(a, b) for i in range(n) ] # 5. На основі listOfRandomNumbers сформувати ітерований об'єкт з парними числами. IterObj = ( i for i in numbers if i%2 == 0 ) # Вираз-генератор з оператором if # 6. Вивести результат у вигляді списків L1 = list(numbers) L2 = list(IterObj) print("L1 = ", L1) print("L2 = ", L2)
Тестовий приклад
n = 10 a = 1 b = 100 L1 = [68, 65, 44, 22, 74, 25, 3, 36, 13, 39] L2 = [68, 44, 22, 74, 36]
⇑
Споріднені теми
- Функції-генератори. Інструкція yield. Методи next(), iter(), send()
- Використання стандартних функцій у поєднанні з виразами-генераторами. Функції sum(), sorted(), map(), all(), any(), min(), max(), filter(), zip(), enumerate()
- Генератори множин. Генератори словників. Множини та вирази-генератори. Словники та вирази-генератори. Приклади
- Використання вкладених конструкцій if та for в генераторах списків, множин та словників
⇑