Оптимизация в Python. Джейд Картер
для которых функция `predicate` возвращает `False`.
– `itertools.groupby(iterable, key)`: Группирует элементы из итерируемого объекта на основе функции `key`.
– `itertools.product(iterable1, iterable2, …)`: Возвращает декартово произведение нескольких итерируемых объектов.
Давайте рассмотрим пример применения модуля `itertools` для оптимизации и измерения производительности кода. Предположим, у нас есть два больших списка, и мы хотим найти пересечение (общие элементы) между ними. Мы можем использовать модуль `itertools` для этой задачи:
```python
import timeit
import itertools
# Создадим два больших списка
list1 = list(range(100000))
list2 = list(range(50000, 150000))
# Измерим время выполнения операции поиска пересечения с использованием цикла
def find_intersection_with_loop():
intersection = []
for item in list1:
if item in list2:
intersection.append(item)
# Измерим время выполнения операции поиска пересечения с использованием itertools
def find_intersection_with_itertools():
intersection = list(itertools.filterfalse(lambda x: x not in list2, list1))
# Измерим время выполнения для поиска с использованием цикла
loop_time = timeit.timeit(find_intersection_with_loop, number=100)
print(f"Поиск с использованием цикла занял {loop_time:.6f} секунд")
# Измерим время выполнения для поиска с использованием itertools
itertools_time = timeit.timeit(find_intersection_with_itertools, number=100)
print(f"Поиск с использованием itertools занял {itertools_time:.6f} секунд")
```
Этот код измеряет время выполнения операции поиска пересечения между двумя списками с использованием цикла и с использованием `itertools`. Здесь мы используем функцию `itertools.filterfalse`, чтобы найти элементы, которые присутствуют в `list1`, но отсутствуют в `list2`. Мы выполняем каждую операцию поиска 100 раз и выводим результаты.
Вы увидите, что операция поиска с использованием `itertools` обычно выполняется быстрее, чем операция с использованием цикла, что позволяет улучшить производительность кода при работе с большими данными.
4. Модуль `functools`
Модуль `functools` в Python предоставляет полезные функции для оптимизации работы с функциями. Одной из наиболее важных функций этого модуля является `lru_cache`, которая позволяет кешировать результаты функций. Это может существенно повысить производительность функций, вызываемых многократно с одними и теми же аргументами.
Разберем пример использования `lru_cache` для оптимизации функции, вычисляющей факториал числа:
```python
import functools
# Декорируем функцию с lru_cache для кеширования результатов
@functools.lru_cache(maxsize=None)
def factorial(n):
if n == 0:
return 1
else:
return n factorial(n – 1)
# Теперь функция будет кешировать результаты
result1 = factorial(5) # Первый вызов, вычисляется и кешируется
result2 = factorial(5) # Второй вызов, результат взят из кеша, не вычисляется снова
print(result1) # Вывод: 120
print(result2) # Вывод: 120
```
В этом примере мы использовали `@functools.lru_cache(maxsize=None)` для декорирования функции `factorial`. Это означает, что при использовании результаты функции будут кешироваться бесконечно или, точнее, пока доступной памяти достаточно для хранения кеша. Когда функция вызывается с определенными аргументами, результат вычисления сохраняется в кеше. При последующих вызовах этой функции