Prema zvaničnoj dokumentaciji Pythona, itertools
predstavlja modul koji nudi kolekciju brzih i memorijski efikasnih alata namenjenih radu sa Python iteratorima. Ovi alati se mogu koristiti pojedinačno ili u kombinaciji, pružajući efikasan i sažet način kreiranja i manipulacije iteratorima uz minimalnu potrošnju memorije.
Modul itertools
sadrži funkcionalnosti koje pojednostavljuju rad sa iteratorima, naročito kada se manipuliše velikim skupovima podataka. Funkcije unutar ovog modula mogu se primenjivati na postojeće iteratore kako bi se formirali kompleksniji iteratori.
Dodatno, itertools
pomaže programerima da umanje greške pri radu sa iteratorima, istovremeno omogućavajući pisanje jasnijeg, čitljivijeg i lakšeg za održavanje koda.
Na osnovu funkcionalnosti koje iteratori iz modula itertools
nude, mogu se grupisati u sledeće kategorije:
1. Beskonačni iteratori
Ovi iteratori omogućavaju rad sa beskonačnim sekvencama i omogućavaju beskonačno izvršavanje petlji ukoliko se ne specificira uslov za izlazak iz petlje. Ovi iteratori su izuzetno korisni prilikom simuliranja beskonačnih petlji ili generisanja neograničenih nizova. itertools
modul obezbeđuje tri beskonačna iteratora: count()
, cycle()
i repeat()
.
2. Kombinatorički iteratori
Kombinatorički iteratori uključuju funkcije koje omogućavaju rad sa Dekartovim proizvodima i izvođenje kombinacija i permutacija elemenata unutar iterabilnog objekta. Ove funkcije se koriste kada je potrebno pronaći sve moguće načine raspoređivanja ili kombinovanja elemenata unutar iterabilnog objekta. itertools
sadrži četiri kombinatorička iteratora: product()
, permutations()
, combinations()
i combinations_with_replacement()
.
3. Iteratori koji se završavaju sa najkraćom ulaznom sekvencom
Ovi iteratori, poznati i kao završni iteratori, se koriste nad konačnim sekvencama i generišu izlaz na osnovu specifične funkcionalnosti. Neki primeri ovih iteratora su: accumulate()
, chain()
, chain.from_iterable()
, compress()
, dropwhile()
, filterfalse()
, groupby()
, islice()
, pairwise()
, starmap()
, takewhile()
, tee()
i zip_longest()
.
Pogledajmo detaljnije kako različite funkcije modula itertools
funkcionišu, grupisane po tipu:
Beskonačni iteratori
Tri beskonačna iteratora uključuju:
1. count()
Funkcija count(start, step)
generiše beskonačan niz brojeva, počevši od zadate početne vrednosti. Funkcija prihvata dva opciona argumenta: start
i step
. Argument start
određuje početnu vrednost niza, a ukoliko se ne navede, podrazumevano počinje od 0. Argument step
definiše razliku između dva uzastopna broja, sa podrazumevanom vrednošću od 1.
import itertools
# brojanje počevši od 4, sa korakom od 2
for i in itertools.count(4, 2):
# uslov za prekidanje petlje, kako bi se izbegla beskonačna petlja
if i == 14:
break
else:
print(i) # ispis - 4, 6, 8, 10, 12
Izlaz
4
6
8
10
12
2. cycle()
Funkcija cycle(iterable)
prihvata iterabilni objekat kao argument i ciklično prolazi kroz elemente tog objekta, omogućavajući pristup svakom elementu po redosledu pojavljivanja.
Na primer, ako prosledimo listu ["crvena", "zelena", "žuta"]
funkciji cycle()
, u prvom ciklusu ćemo imati pristup „crvena“, u drugom „zelena“, a u trećem „žuta“. U četvrtom ciklusu, pošto su svi elementi iterabilnog objekta iscrpljeni, ponovo ćemo početi od „crvena“, i tako beskonačno.
Kada pozivate funkciju cycle()
, njen rezultat treba sačuvati u promenljivoj kako bi se kreirao iterator koji čuva svoje stanje. Ovo osigurava da ciklus ne počinje iznova svaki put, i omogućava pristup svim elementima redom.
import itertools
colors = ["crvena", "zelena", "žuta"]
# prosleđivanje liste boja funkciji cycle()
color_cycle = itertools.cycle(colors)
print(color_cycle)
# range se koristi za zaustavljanje beskonačne petlje nakon što ispišemo 7 elemenata
# next() se koristi za dobijanje sledećeg elementa iz iteratora
for i in range(7):
print(next(color_cycle))
Izlaz:
crvena
zelena
žuta
crvena
zelena
žuta
crvena
3. repeat()
Funkcija repeat(elem, n)
prihvata dva argumenta, element koji se ponavlja (elem
) i broj ponavljanja elementa (n
). Element koji se ponavlja može biti pojedinačna vrednost ili iterabilni objekat. Ako se argument n
ne prosledi, element će se ponavljati beskonačno.
import itertools
for i in itertools.repeat(10, 3):
print(i)
Izlaz:
10
10
10
Kombinatorički iteratori
Kombinatorički iteratori obuhvataju:
1. product()
product()
je funkcija koja se koristi za izračunavanje Dekartovog proizvoda iterabilnih objekata koji joj se proslede. Ako imamo dva iterabilna objekta ili skupa, npr. x = {7, 8}
i y = {1, 2, 3}
, Dekartov proizvod x
i y
će sadržati sve moguće kombinacije elemenata iz x
i y
, pri čemu je prvi element iz x
a drugi iz y
. Dekartov proizvod x
i y
u ovom slučaju je [(7, 1), (7, 2), (7, 3), (8, 1), (8, 2), (8, 3)]
.
Funkcija product()
prihvata opcioni parametar repeat
koji se koristi za izračunavanje Dekartovog proizvoda iterabilnog objekta sa samim sobom. repeat
specificira broj ponavljanja za svaki element iz ulaznih iterabilnih objekata prilikom izračunavanja Dekartovog proizvoda.
Na primer, pozivanje product('ABCD', repeat=2)
daje kombinacije kao što su ('A', 'A')
, ('A', 'B')
, ('A', 'C')
, i tako dalje. Ako je repeat
postavljen na 3, funkcija bi dala kombinacije poput ('A', 'A', 'A')
, ('A', 'A', 'B')
, ('A', 'A', 'C')
, ('A', 'A', 'D')
, i tako dalje.
from itertools import product
# product() sa opcionim argumentom repeat
print("product() sa opcionim argumentom repeat ")
print(list(product('ABC', repeat = 2)))
# product() bez repeat argumenta
print("product() BEZ opcionog argumenta repeat")
print(list(product([7,8], [1,2,3])))
Izlaz
product() sa opcionim argumentom repeat
[('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'B'), ('B', 'C'), ('C', 'A'), ('C', 'B'), ('C', 'C')]
product() BEZ opcionog argumenta repeat
[(7, 1), (7, 2), (7, 3), (8, 1), (8, 2), (8, 3)]
2. permutations()
Funkcija permutations(iterable, group_size)
vraća sve moguće permutacije elemenata iterabilnog objekta koji joj je prosleđen. Permutacija predstavlja broj načina na koji se elementi u skupu mogu rasporediti. Funkcija permutations()
prihvata opcioni argument group_size
. Ako group_size
nije naveden, generisane permutacije će biti iste veličine kao i dužina iterabilnog objekta prosleđenog funkciji.
import itertools
numbers = [1, 2, 3]
sized_permutations = list(itertools.permutations(numbers,2))
unsized_permuatations = list(itertools.permutations(numbers))
print("Permutacije sa veličinom grupe od 2")
print(sized_permutations)
print("Permutacije BEZ argumenta veličine")
print(unsized_permuatations)
Izlaz
Permutacije sa veličinom grupe od 2
[(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]
Permutacije BEZ argumenta veličine
[(1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1)]
3. combinations()
Funkcija combinations(iterable, size)
vraća sve moguće kombinacije iterabilnog objekta date dužine iz elemenata unutar iterabilnog objekta prosleđenog funkciji. Argument size
definiše veličinu svake kombinacije.
Rezultati su sortirani. Kombinacija se malo razlikuje od permutacije. Kod permutacije, redosled je bitan, dok kod kombinacije, redosled nije bitan. Na primer, u nizu [A, B, C]
postoji 6 permutacija: AB, AC, BA, BC, CA, CB, ali samo 3 kombinacije: 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("Kombinacije sa veličinom od 2")
print(size2_combination)
print("Kombinacije sa veličinom od 3")
print(size3_combination)
Izlaz:
Kombinacije sa veličinom od 2
[(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]
Kombinacije sa veličinom od 3
[(1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]
4. combinations_with_replacement()
Funkcija combinations_with_replacement(iterable, size)
generiše sve moguće kombinacije iterabilnog objekta date dužine iz elemenata prosleđenog iterabilnog objekta, dopuštajući ponavljanje elemenata u izlaznim kombinacijama. Veličina (size
) određuje dužinu generisanih kombinacija.
Ova funkcija se razlikuje od combinations()
po tome što daje kombinacije u kojima se element može ponoviti više puta. Na primer, možete dobiti kombinaciju poput (1,1)
, što nije moguće sa funkcijom combinations()
.
import itertools
numbers = [1, 2, 3,4]
size2_combination = list(itertools.combinations_with_replacement(numbers,2))
print("Combinations_with_replacement => veličina 2")
print(size2_combination)
Izlaz
Combinations_with_replacement => veličina 2
[(1, 1), (1, 2), (1, 3), (1, 4), (2, 2), (2, 3), (2, 4), (3, 3), (3, 4), (4, 4)]
Završni iteratori
Ovo uključuje iteratore kao što su:
1. accumulate()
Funkcija accumulate(iterable, function)
prihvata iterabilni objekat i drugi opcioni argument, koji je funkcija. Zatim vraća akumulirani rezultat primene funkcije u svakoj iteraciji na elemente iterabilnog objekta. Ako funkcija nije prosleđena, vrši se sumiranje i vraćaju se akumulirani rezultati.
import itertools
import operator
numbers = [1, 2, 3, 4, 5]
# Akumulacija sume brojeva
accumulated_val = itertools.accumulate(numbers)
accumulated_mul = itertools.accumulate(numbers, operator.mul)
print("Akumulacija bez funkcije")
print(list(accumulated_val))
print("Akumulacija sa množenjem")
print(list(accumulated_mul))
Izlaz:
Akumulacija bez funkcije
[1, 3, 6, 10, 15]
Akumulacija sa množenjem
[1, 2, 6, 24, 120]
2. chain()
Funkcija chain(iterable_1, iterable_2, ...)
prihvata više iterabilnih objekata i spaja ih zajedno, kreirajući jedan iterabilni objekat koji sadrži sve vrednosti iz iterabilnih objekata koji su prosleđeni funkciji chain()
.
import itertools
letters = ['A', 'B', 'C', 'D']
numbers = [1, 2, 3]
colors = ['crvena', 'zelena', 'žuta']
# Spajanje slova, brojeva i boja zajedno
chained_iterable = list(itertools.chain(letters, numbers, colors))
print(chained_iterable)
Izlaz:
['A', 'B', 'C', 'D', 1, 2, 3, 'crvena', 'zelena', 'žuta']
3. chain.from_iterable()
Funkcija chain.from_iterable(iterable)
je slična funkciji chain()
. Međutim, razlika je u tome što prihvata samo jedan iterabilni objekat koji sadrži pod-iterabilne objekte i spaja ih zajedno.
import itertools
letters = ['A', 'B', 'C', 'D']
numbers = [1, 2, 3]
colors = ['crvena', 'zelena', 'žuta']
iterable = ['zdravo',colors, letters, numbers]
chain = list(itertools.chain.from_iterable(iterable))
print(chain)
Izlaz:
['z', 'd', 'r', 'a', 'v', 'o', 'crvena', 'zelena', 'žuta', 'A', 'B', 'C', 'D', 1, 2, 3]
4. compress()
Funkcija compress(data, selectors)
prihvata dva argumenta, data
, koji predstavlja iterabilni objekat sa podacima, i selectors
, koji predstavlja iterabilni objekat koji sadrži logičke vrednosti True
i False
. Takođe, 1 i 0 se mogu koristiti kao alternative logičkim vrednostima True
i False
. Funkcija compress()
zatim filtrira podatke koristeći odgovarajuće elemente prosleđene u selektorima.
Vrednosti iz podataka koje odgovaraju vrednosti True
ili 1 u selektoru se biraju, dok se one koje odgovaraju vrednosti False
ili 0 ignorišu. Ako prosledite manje logičkih vrednosti u selektorima od broja stavki u podacima, svi elementi izvan prosleđenih logičkih vrednosti u selektorima se zanemaruju.
import itertools
# podaci imaju 10 elemenata
data = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J']
# prosleđivanje 9 selektorskih elemenata
selectors = [True, False, 1, False, 0, 1, True, False, 1]
# Odabir elemenata iz podataka na osnovu selektora
filtered_data = list(itertools.compress(data, selectors))
print(filtered_data)
Izlaz:
['A', 'C', 'F', 'G', 'I']
5. dropwhile()
Funkcija dropwhile(function, sequence)
prihvata funkciju sa uslovom koji vraća True
ili False
, i niz vrednosti. Zatim odbacuje sve vrednosti dok prosleđeni uslov ne vrati False
. Kada uslov vrati False
, preostali elementi su uključeni u rezultat, bez obzira da li bi vratili True
ili False
.
import itertools
numbers = [1, 2, 3, 4, 5, 1, 6, 7, 2, 1, 8, 9, 0, 7]
# Odbacivanje elemenata dok prosleđeni uslov ne postane False
filtered_numbers = list(itertools.dropwhile(lambda x: x < 5, numbers))
print(filtered_numbers)
Izlaz:
[5, 1, 6, 7, 2, 1, 8, 9, 0, 7]
6. filterfalse()
Funkcija filterfalse(function, sequence)
prihvata funkciju sa uslovom koji se procenjuje kao True
ili False
, i niz. Zatim vraća vrednosti iz niza koje ne zadovoljavaju uslov definisan u funkciji.
import itertools
numbers = [1, 2, 3, 4, 2, 3, 5, 6, 5, 8, 1, 2, 3, 6, 2, 7, 4, 3]
# Filtriranje elemenata za koje uslov vraća False
filtered_numbers = list(itertools.filterfalse(lambda x: x < 4, numbers))
print(filtered_numbers)
Izlaz:
[4, 5, 6, 5, 8, 6, 7, 4]
7. groupby()
Funkcija groupby(iterable, key)
prihvata iterabilni objekat i ključ, a zatim kreira iterator koji vraća uzastopne ključeve i grupe. Da bi funkcionisala, iterabilni objekat koji joj se prosleđuje treba da bude sortiran po istoj funkciji ključa. Funkcija ključa je ključna vrednost za svaki element u iterabilnom objektu.
import itertools
input_list = [("Domaće", "Krava"), ("Domaće", "Pas"), ("Domaće", "Mačka"),("Divlje", "Lav"), ("Divlje", "Zebra"), ("Divlje", "Slon")]
classification = itertools.groupby(input_list,lambda x: x[0])
for key,value in classification:
print(key,":",list(value))
Izlaz:
Domaće : [('Domaće', 'Krava'), ('Domaće', 'Pas'), ('Domaće', 'Mačka')]
Divlje : [('Divlje', 'Lav'), ('Divlje', 'Zebra'), ('Divlje', 'Slon')]
8. islice()
Funkcija islice(iterable, start, stop, step)
omogućava da se „iseče“ iterabilni objekat koristeći prosleđene vrednosti početka (start
), zaustavljanja (stop
) i koraka (step
). Argument step
je opcioni. Brojanje počinje od 0, a stavka na poziciji stop
nije uključena u rezultat.
import itertools
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
# Odabir elemenata u određenom rasponu
selected_numbers = list(itertools.islice(numbers, 2, 10))
selected_numbers_step= list(itertools.islice(numbers, 2, 10,2))
print("islice bez podešavanja koraka")
print(selected_numbers)
print("islice sa vrednošću koraka od 2")
print(selected_numbers_step)
Izlaz:
islice bez podešavanja koraka
[3, 4, 5, 6, 7, 8, 9, 10]
islice sa vrednošću koraka od 2
[3, 5, 7, 9]
9. pairwise()
Funkcija pairwise(iterable)
vraća uzastopne parove koji se preklapaju, preuzete iz iterabilnog objekta koji joj je prosleđen, po redosledu pojavljivanja u iterabilnom objektu. Ako iterabilni objekat koji je prosleđen ima manje od dve vrednosti, rezultat funkcije pairwise()
će biti prazan.
from itertools import pairwise
numbers = [1, 2, 3, 4, 5, 6, 7, 8]
word = 'SVET'
single = ['A']
print(list(pairwise(numbers)))
print(list(pairwise(word)))
print(list(pairwise(single)))
Izlaz:
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8)]
[('S', 'V'), ('V', 'E'), ('E', 'T')]
[]
10. starmap()
Funkcija starmap(function, iterable)
se koristi umesto funkcije map()
kada su argumenti parametara već grupisani u torke. Funkcija starmap()
primenjuje funkciju na elemente iterabilnog objekta koji su joj prosleđeni. Iterabilni objekat treba da ima elemente grupisane u torke.
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)))
Izlaz:
[13, 5, 9, 16, 11]
11. takewhile()
Funkcija takewhile(function, iterable)
radi suprotno od funkcije dropwhile()
. Funkcija takewhile()
prihvata funkciju sa uslovom za evaluaciju i iterabilni objekat. Zatim uključuje sve elemente u iterabilnom objektu koji zadovoljavaju uslov u funkciji, sve dok se ne vrati False
. Kada se vrati False
, svi sledeći elementi u iterabilnom objektu se zanemaruju.
import itertools
numbers = [1, 2, 3, 4, 5, 1, 6, 7, 2, 1, 8, 9, 0, 7]
# Odabir elemenata dok prosleđeni uslov ne postane False
filtered_numbers = list(itertools.takewhile(lambda x: x < 5, numbers))
print(filtered_numbers)
Izlaz:
[1, 2, 3, 4]
12. tee()
Funkcija tee(iterable, n)
prihvata iterabilni objekat i vraća više nezavisnih iteratora. Broj iteratora koji se vraćaju se podešava sa n
, čija je podrazumevana vrednost 2.
import itertools
numbers = [1, 2, 3, 4, 5]
# Kreiranje dva nezavisna iteratora iz brojeva
iter1, iter2 = itertools.tee(numbers, 2)
print(list(iter1))
print(list(iter2))
Izlaz:
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
13. zip_longest()
Funkcija zip_longest(iterables, fillvalue)
prihvata više iteratora i vrednost za popunjavanje (fillvalue
). Zatim vraća iterator koji agregira elemente iz svakog od iteratora koji su joj prosleđeni. Ako iteratori nisu iste dužine, nedostajuće vrednosti se popunjavaju vrednošću prosleđenom funkciji, dok se ne iscrpi najduži iterabilni objekat.
import itertools
names = ['Jovan', 'Matej', 'Marija', 'Ana', 'Bob', 'Čarli', 'Furi']
ages = [25, 30, 12, 13, 42]
# Kombinovanje imena i godina, popunjavanje nedostajućih godina sa crticom
combined = itertools.zip_longest(names, ages, fillvalue="-")
for name, age in combined:
print(name, age)
Izlaz:
Jovan 25
Matej 30
Marija 12
Ana 13
Bob 42
Čarli -
Furi -
Zaključak
Python itertools
je izuzetno važan set alata za Python programere. Python itertools
se naširoko koristi u funkcionalnom programiranju, obradi i transformaciji podataka, filtriranju i selekciji podataka, grupisanju i agregaciji, kombinovanju iterabilnih objekata, kombinatorici, kao i prilikom rada sa beskonačnim nizovima.
Kao Python programer, imaćete veliku korist od učenja o itertools
, stoga obavezno koristite ovaj članak da biste se upoznali sa Python itertools
.