Що таке функції Python Itertools?

Згідно з документацією Python, Itertools — це модуль Python, який надає набір швидких і ефективних з використанням пам’яті інструментів для роботи з ітераторами Python. Ці інструменти можна використовувати як окремо, так і в комбінації, і вони дають змогу стисло та ефективно створювати ітератори та працювати з ними швидко та з ефективним використанням пам’яті.

Модуль Itertools містить функції, які полегшують роботу з ітераторами, особливо під час обробки великих наборів даних. Функції Itertools можуть працювати з існуючими ітераторами для створення ще більш складних ітераторів Python.

Крім того, Itertools може допомогти розробникам зменшити кількість помилок під час роботи з ітераторами та писати чистіший, читабельний і підтримуваний код.

Виходячи з функціональних можливостей, які надають ітератори в модулі Itertools, їх можна класифікувати на такі типи:

#1. Нескінченні ітератори

Це ітератори, які дозволяють вам працювати з нескінченними послідовностями та нескінченно запускати цикл, якщо немає умови для виходу з циклу. Такі ітератори корисні при моделюванні нескінченних циклів або генерації необмеженої послідовності. Itertools має три нескінченні ітератори, які включають count(), cycle() і repeat().

#2. Комбінаторні ітератори

Комбінаторні ітератори містять функції, які можна використовувати для роботи з декартовими продуктами та виконання комбінацій і перестановок елементів, що містяться в ітераторі. Це основні функції, коли ви намагаєтеся знайти всі можливі способи впорядкувати або об’єднати елементи в ітерації. Itertools має чотири комбінаторні ітератори. Це product(), permutations(), combinations() і combinations_with_replacement().

#3. Ітератори завершуються на найкоротшій вхідній послідовності

Це кінцеві ітератори, які використовуються на кінцевих послідовностях і генерують вихідні дані на основі типу використовуваної функції. Приклади цих кінцевих ітераторів включають: collecte(), chain(), chain.from_iterable(), compress(), dropwhile(), filterfalse(), groupby(), islice(), pairwise(), starmap(), takewhile (), tee() і zip_longest().

Давайте розглянемо, як працюють різні функції Itertools залежно від їх типу:

Нескінченні ітератори

Три нескінченні ітератори включають:

#1. рахувати()

Функція count(start, step) генерує нескінченну послідовність чисел, починаючи з початкового значення. Функція приймає два необов’язкові аргументи: початок і крок. Аргумент «початок» визначає, де має починатися послідовність чисел. За замовчуванням він починається з 0, якщо початкове значення не вказано. step встановлює різницю між кожним послідовним числом. Стандартне значення кроку – 1.

import itertools
# count starting at 4, making steps of 2  
for i in itertools.count(4, 2):
    # condition to end the loop avoiding infinite looping
    if i == 14:
        break
    else:
        print(i) # output - 4, 6, 8, 10, 12

Вихід

4
6
8
10
12

#2. цикл()

Функція cycle(iterable) приймає iterable як аргумент, а потім циклічно перебирає iterable, надаючи доступ до елементів у iterable у порядку їх появи.

Наприклад, якщо ми проходимо [“red”, “green”, “yellow”] у cycle(), у першому циклі ми матимемо доступ до «червоного»; у другому циклі ми матимемо доступ до «зеленого», потім до «жовтого». У четвертому циклі, оскільки всі елементи в ітерації вичерпано, ми почнемо спочатку з «червоного», а потім продовжуватимемо нескінченно.

Під час виклику cycle() ви зберігаєте його результат у змінній, щоб створити ітератор, який підтримує його стан. Це гарантує, що цикл не починається щоразу спочатку, надаючи вам доступ лише до першого елемента.

import itertools

colors = ["red", "green", "yellow"]
# pass in colors into cycle()
color_cycle = itertools.cycle(colors)
print(color_cycle)

# range used to stop the infinite loop once we've printed 7 times
# next() used to return the next item from the iterator
for i in range(7):
    print(next(color_cycle))

Вихід:

red
green
yellow
red
green
yellow
red

#3. повторити()

repeat(elem,n) приймає два аргументи, елемент, який потрібно повторити (elem), і кількість разів, які ви хочете повторити елемент(n). Елемент, який ви хочете повторити, може бути одним значенням або ітерованим. Якщо ви не введете n, елемент повторюватиметься нескінченно.

import itertools
   
for i in itertools.repeat(10, 3):
    print(i)

Вихід:

10 
10
10

Комбінаторні ітератори

Комбінаторні ітератори включають:

  Що таке розбиті тіні та роздуті відблиски?

#1. продукт()

product() — це функція, яка використовується для обчислення декартового добутку переданого їй ітератора. Якщо у нас є дві ітерації або набори, наприклад, x = {7,8} і y = {1,2,3}, декартів добуток x і y міститиме всі можливі комбінації елементів з x і y, де перший елемент з x, а другий з y. Декартовий добуток x і y в цьому випадку дорівнює [(7, 1), (7, 2), (7, 3), (8, 1), (8, 2), (8, 3)].

product() приймає додатковий параметр під назвою repeat, який використовується для обчислення декартового добутку ітерованого елемента з самим собою. repeat визначає кількість повторень для кожного елемента з вхідних ітерацій під час обчислення декартового добутку.

Наприклад, виклик product(‘ABCD’, repeat=2) дає такі комбінації, як (‘A’, ‘A’), (‘A’, ‘B’), (‘A’, ‘C’) тощо на. Якщо для повтору було встановлено значення 3, функція видавала б такі комбінації, як (‘A’, ‘A’, ‘A’), (‘A’, ‘A’, ‘B’), (‘A’, ‘A’ , ‘C’), (‘A’, ‘A’, ‘D’) і так далі.

from itertools import product
# product() with the optional repeat argument
print("product() with the optional repeat argument ")
print(list(product('ABC', repeat = 2)))

# product with no repeat
print("product() WITHOUT an optional repeat argument")
print(list(product([7,8], [1,2,3])))

Вихід

product() with the optional repeat argument 
[('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'B'), ('B', 'C'), ('C', 'A'), ('C', 'B'), ('C', 'C')]
product() WITHOUT an optional repeat argument
[(7, 1), (7, 2), (7, 3), (8, 1), (8, 2), (8, 3)]

#2. перестановки()

permutations(iterable, group_size) повертає всі можливі перестановки переданого в нього iterable. Перестановка представляє кількість способів упорядкування елементів у наборі. permutations() приймає необов’язковий аргумент group_size. Якщо group_size не вказано, згенеровані перестановки будуть того самого розміру, що й довжина ітерованого елемента, переданого у функцію

import itertools
numbers = [1, 2, 3]
sized_permutations = list(itertools.permutations(numbers,2))
unsized_permuatations = list(itertools.permutations(numbers))

print("Permutations with a size of 2")
print(sized_permutations)
print("Permutations with NO size argument")
print(unsized_permuatations)

Вихід

Permutations with a group size of 2
[(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]
Permutations with NO size argument
[(1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1)]

#3. комбінації()

combinations(iterable, size) повертає всі можливі комбінації iterable заданої довжини з елементів у iterable, переданих у функцію. Аргумент size визначає розмір кожної комбінації.

Результати впорядковані. Комбінація дещо відрізняється від перестановки. При перестановці порядок має значення, а при комбінації порядок не має значення. Наприклад, в [A, B, C] є 6 перестановок: AB, AC, BA, BC, CA, CB, але лише 3 комбінації AB, AC, BC.

import itertools
numbers = [1, 2, 3,4]
size2_combination = list(itertools.combinations(numbers,2))
size3_combination = list(itertools.combinations(numbers, 3))

print("Combinations with a size of 2")
print(size2_combination)
print("Combinations with a size of 3")
print(size3_combination)

Вихід:

Combinations with a size of 2
[(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]
Combinations with a size of 3
[(1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]

#4. комбінації_із_заміною()

combinations_with_replacement(iterable, size) генерує всі можливі комбінації iterable заданої довжини з iterable, переданого у функцію, і допускає повторювані елементи у вихідних комбінаціях. Розмір визначає розмір згенерованих комбінацій.

Ця функція відрізняється від combinations() тим, що вона дає комбінації, де елемент може повторюватися більше одного разу. Наприклад, ви можете отримати таку комбінацію, як (1,1), яку ви не можете отримати за допомогою комбінації().

import itertools
numbers = [1, 2, 3,4]

size2_combination = list(itertools.combinations_with_replacement(numbers,2))
print("Combinations_with_replacement => size 2")
print(size2_combination)

Вихід

Combinations_with_replacement => size 2
[(1, 1), (1, 2), (1, 3), (1, 4), (2, 2), (2, 3), (2, 4), (3, 3), (3, 4), (4, 4)]

Кінцеві ітератори

Це включає такі ітератори, як:

  Як створити обмеження зовнішнього ключа в SQL

#1. накопичувати()

collecte(iterable, function) приймає iterable і другий необов’язковий аргумент, який є функцією. Потім він повертає накопичений результат застосування функції в кожній ітерації до елементів ітерованого. Якщо жодна функція не передана, виконується додавання та повертаються накопичені результати.

import itertools
import operator
numbers = [1, 2, 3, 4, 5]

# Accumulate the sum of numbers
accumulated_val = itertools.accumulate(numbers)
accumulated_mul = itertools.accumulate(numbers, operator.mul)
print("Accumulate with no function")
print(list(accumulated_val))
print("Accumulate with multiplication")
print(list(accumulated_mul))

Вихід:

Accumulate with no function
[1, 3, 6, 10, 15]
Accumulate with multiplication
[1, 2, 6, 24, 120]

#2. ланцюг()

chain(iterable_1, iterable_2, …) бере кілька ітераторів і з’єднує їх у ланцюжок, створюючи один ітератор, що містить значення з ітераторів, переданих у функцію chain()

import itertools

letters = ['A', 'B', 'C', 'D']
numbers = [1, 2, 3]
colors = ['red', 'green', 'yellow']

# Chain letters and numbers together
chained_iterable = list(itertools.chain(letters, numbers, colors))
print(chained_iterable)

Вихід:

['A', 'B', 'C', 'D', 1, 2, 3, 'red', 'green', 'yellow']

#3. chain.from_iterable()

chain.from_iterable(iterable) ця функція схожа на chain(). Однак він відрізняється від ланцюга тим, що він бере лише один ітератор, який містить підітератори, і об’єднує їх разом.

import itertools

letters = ['A', 'B', 'C', 'D']
numbers = [1, 2, 3]
colors = ['red', 'green', 'yellow']

iterable = ['hello',colors, letters, numbers]
chain = list(itertools.chain.from_iterable(iterable))
print(chain)

Вихід:

['h', 'e', 'l', 'l', 'o', 'red', 'green', 'yellow', 'A', 'B', 'C', 'D', 1, 2, 3]

#4. стиснути()

compress(data, selectors) приймає два аргументи: дані, які є ітерованими, і селектори, які є ітерованими, що містять логічні значення true та false. 1, 0 також можна використовувати як альтернативи логічним значенням true і false. compress() потім фільтрує передані дані за допомогою відповідних елементів, переданих у селекторі.

Значення в даних, які відповідають значенню true або 1 у селекторі, вибираються, а решта, які відповідають false або 0, ігноруються. Якщо ви передаєте в селекторах менше логічних значень, ніж кількість елементів у даних, усі елементи поза переданими логічними значеннями в селекторах ігноруються

import itertools

# data has 10 items
data = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J']
# passing in 9 selector items
selectors = [True, False, 1, False, 0, 1, True, False, 1]

# Select elements from data based on selectors
filtered_data = list(itertools.compress(data, selectors))
print(filtered_data)

Вихід:

['A', 'C', 'F', 'G', 'I']

#5. dropwhile()

dropwhile(функція, послідовність) приймає функцію з умовою, яка повертає true або false, і послідовність значень. Потім він видаляє всі значення, доки виконана умова не поверне значення False. Якщо умова повертає false, решта елементів включаються до її результатів незалежно від того, повернули б вони True чи False.

import itertools

numbers = [1, 2, 3, 4, 5, 1, 6, 7, 2, 1, 8, 9, 0, 7]

# Drop elements until the passed condition is False
filtered_numbers = list(itertools.dropwhile(lambda x: x < 5, numbers))
print(filtered_numbers)

Вихід:

[5, 1, 6, 7, 2, 1, 8, 9, 0, 7]

#6. filterfalse()

filterfalse(функція, послідовність) приймає функцію з умовою, яка має значення true або false, і послідовність. Потім він повертає значення з послідовності, які не задовольняють умову у функції.

import itertools

numbers = [1, 2, 3, 4, 2, 3 5, 6, 5, 8, 1, 2, 3, 6, 2, 7, 4, 3]

# Filter elements for which condition is False
filtered_numbers = list(itertools.filterfalse(lambda x: x < 4, numbers))
print(filtered_numbers)

Вихід:

[4, 5, 6, 5, 8, 6, 7, 4]

#7. groupby()

groupby(iterable, key) приймає iterable і ключ, а потім створює ітератор, який повертає послідовні ключі та групи. Щоб він працював, переданий йому ітератор має бути відсортований за тією самою ключовою функцією. Ключова функція комп’ютера – ключове значення для кожного елемента в ітерації.

import itertools

input_list = [("Domestic", "Cow"), ("Domestic", "Dog"), ("Domestic", "Cat"),("Wild", "Lion"), ("Wild", "Zebra"), ("Wild", "Elephant")]
classification = itertools.groupby(input_list,lambda x: x[0])
for key,value in classification:
  print(key,":",list(value))

Вихід:

Domestic : [('Domestic', 'Cow'), ('Domestic', 'Dog'), ('Domestic', 'Cat')]
Wild : [('Wild', 'Lion'), ('Wild', 'Zebra'), ('Wild', 'Elephant')]

#8. islice()

islice(iterable, start, stop, step) дозволяє розділяти ітераційний елемент за допомогою переданих значень start, stop і step. Аргумент крок необов’язковий. Підрахунок починається з 0, і елемент у номері зупинки не включається.

import itertools

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]

# Select elements within a range
selected_numbers = list(itertools.islice(numbers, 2, 10))
selected_numbers_step= list(itertools.islice(numbers, 2, 10,2))
print("islice without setting a step value")
print(selected_numbers)
print("islice with a step value of 2")
print(selected_numbers_step)

Вихід:

islice without setting a step value
[3, 4, 5, 6, 7, 8, 9, 10]
islice with a step value of 2
[3, 5, 7, 9]

#9. попарно()

pairwise(iterable) повертає послідовні пари, що перекриваються, взяті з iterable, переданого йому в тому порядку, в якому вони з’являються в iterable. Якщо переданий ітератор має менше двох значень, результат від pairwise() буде порожнім.

from itertools import pairwise

numbers = [1, 2, 3, 4, 5, 6, 7, 8]
word = 'WORLD'
single = ['A']

print(list(pairwise(numbers)))
print(list(pairwise(word)))
print(list(pairwise(single)))

Вихід:

[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8)]
[('W', 'O'), ('O', 'R'), ('R', 'L'), ('L', 'D')]
[]

#10. зіркова карта()

starmap(function, iterable) — це функція, яка використовується замість map(), коли параметри аргументів уже згруповані в кортежі. startmap() застосовує функцію до переданих йому елементів iterable. Ітератор повинен мати елементи, згруповані в кортежі.

import itertools

iter_starmap = [(123, 63, 13), (5, 6, 52), (824, 51, 9), (26, 24, 16), (14, 15, 11)]
print (list(itertools.starmap(min, iter_starmap)))

Вихід:

[13, 5, 9, 16, 11]

#11. забрати()

takewhile(функція, iterable) працює протилежно до dropwhile(). takewhile() приймає функцію з умовою для оцінки та можливістю повторення. Потім він включає всі елементи в ітерацію, які задовольняють умову у функції, доки не буде повернено False. Коли False повертається, усі наступні елементи в iterable ігноруються.

import itertools

numbers = [1, 2, 3, 4, 5, 1, 6, 7, 2, 1, 8, 9, 0, 7]

# Drop elements until the passed condition is False
filtered_numbers = list(itertools.takewhile(lambda x: x < 5, numbers))
print(filtered_numbers)

Вихід:

[1, 2, 3, 4]

#12. футболка()

tee(iterable, n) приймає iterable і повертає кілька незалежних ітераторів. Кількість ітераторів для повернення встановлюється n, яке за замовчуванням дорівнює 2.

import itertools

numbers = [1, 2, 3, 4, 5]

# Create two independent iterators from numbers
iter1, iter2 = itertools.tee(numbers, 2)
print(list(iter1))
print(list(iter2))

Вихід:

[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]

#13. zip_longest()

zip_longest(iterables, fillvalue) приймає кілька ітераторів і fillvalue. Потім він повертає ітератор, який агрегує елементи з кожного з переданих йому ітераторів. Якщо ітератори не мають однакової довжини, відсутні значення замінюються значенням fillvalue, переданим у функцію, доки не буде вичерпано найдовший ітератор.

import itertools

names = ['John', 'mathew', 'mary', 'Alice', 'Bob', 'Charlie', 'Fury']
ages = [25, 30, 12, 13, 42]

# Combine name and ages, filling in missing ages with a dash
combined = itertools.zip_longest(names, ages, fillvalue="-")

for name, age in combined:
    print(name, age)

Вихід:

John 25
mathew 30
mary 12
Alice 13
Bob 42
Charlie -
Fury -

Висновок

Python itertools є важливим набором інструментів для розробника Python. Інструменти Python itertools широко використовуються у функціональному програмуванні, обробці та перетворенні даних, фільтрації та відборі даних, групуванні та агрегації, об’єднанні ітерованих елементів, комбінаториці та під час роботи з нескінченними послідовностями.

  Що таке розбиті тіні та роздуті відблиски?

Ви як розробник Python отримаєте значну користь, дізнавшись про itertools, тому обов’язково скористайтеся цією статтею, щоб ознайомитися з Python Itertools.