Антонина в целях экономии памяти компьютера вместо последовательности чисел от 1 до миллиона в виде списка решила создать ленивый итератор numbers с помощью функции range(). Затем в двух разных местах своего скрипта она делала проверку того, есть ли число 2000 в этой коллекции.
В первом случае код вернул True, а во втором False.
Объясните ученице ее ошибку и предложите способ исправления ситуации.
Код – IDE
--
numbers = iter(range(1, 1000001))
print(2000 in numbers)
print(2000 in numbers)
Результат выполнения
---
True
False
import sys
numbers = iter(range(1, 1000001))
print(sys.getsizeof(numbers))
numbers = range(1, 1000001)
print(sys.getsizeof(numbers))
32
48
print(next(numbers))
2001
Создайте функцию infinite(lst, tries), которая будет проходиться по элементам списка lst (целые числа) заданное количество раз (tries) циклически.
Один раз - один элемент списка.
После вывода последнего значения последовательности процедура начнется с самого начала.
Например, если в списке 2 элемента, а функция получила значение 3, то сначала выведется первый объект, потом последний, а потом опять первый.
Результат работы функции представьте в виде строки, состоящей из tries количества символов.
from itertools import cycle
def infinite(lst, iterations):
result = ''
iter_lst = cycle(lst)
if lst:
for symbol in range(iterations):
result += str(next(iter_lst))
return result
# Тесты
print(infinite([2, 5, 8], 7))
print(infinite([], 1000))
print(infinite([7], 4))
2582582
# Пустая строка
7777
Инструкция yield позволяет создавать генераторы.
В отличие от объявления return в функции, где возвращается один объект, yield при каждом вызове функции генерирует новый объект.
Фактически это дает возможность использовать генераторы в циклах.
Самая важная причина применения такой инструкции - экономия памяти, когда не требуется сохранять всю последовательность, а можно получать ее элементы по одному.
Ученик написал генератор show_letters(some_str), выводящий все символы строки на печать, но только в том случае, если они являются буквами (остальные игнорируются).
Сократите код функции.
Код – IDE
---
def show_letters(some_str):
clean_str = ''.join([letter for letter in some_str if letter.isalpha()])
for symbol in clean_str:
yield symbol
def show_letters(some_str):
yield from ''.join([letter for letter in some_str if letter.isalpha()])
random_str = show_letters('A!sdf 09 _ w')
print(next(random_str))
print(next(random_str))
A
s
Числа Фибоначчи представляют последовательность, получаемую в результате сложения двух предыдущих элементов.
Начинается коллекция с чисел 1 и 1.
Она достаточно быстро растет, поэтому вычисление больших значений занимает немало времени.
Создайте функцию fib(n), генерирующую n чисел Фибоначчи с минимальными затратами ресурсов.
Для реализации этой функции потребуется обратиться к инструкции yield.
Она не сохраняет в оперативной памяти огромную последовательность, а дает возможность “доставать” промежуточные результаты по одному.
def fib(n):
fib0 = 1
yield fib0
fib1 = 1
yield fib1
for i in range(n - 2):
fib0, fib1 = fib1, fib0 + fib1
yield fib1
# Тест
for num in fib(112121):
pass
print(num)
3578717901141606491845…
Реализуйте итератор колоды карт (52 штуки) CardDeck. Каждая карта представлена в виде строки типа «2 Пик». При вызове функции next() будет представлена следующая карта. По окончании перебора всех элементов возникнет ошибка StopIteration.
class CardDeck:
def __init__(self):
self.length = 52
self.index = 0
self.__SUITS = ['Пик', 'Бубей', 'Червей', 'Крестей']
self.__RANKS = [*range(2, 11), 'J', 'Q', 'K', 'A']
def __len__(self):
return self.length
def __next__(self):
if self.index >= self.length:
raise StopIteration
else:
suit = self.__SUITS[self.index // len(self.__RANKS)]
rank = self.__RANKS[self.index % len(self.__RANKS)]
self.index += 1
return f'{rank} {suit}'
def __iter__(self):
return self
deck = CardDeck()
while True:
print(next(deck))
2 Пик
3 Пик
4 Пик
…
K Крестей
A Крестей
StopIteration