U Pythonu je jednostavno koristiti zapis razumijevanja popisa prilikom generiranja novog popisa.(List comprehensions
)
- 5. Data Structures — List Comprehensions — Python 3.10.0 Documentation
- 6. Expressions — Displays for lists, sets and dictionaries — Python 3.10.0 Documentation
U ovom članku prvo ćemo razgovarati o sljedećem
- Osnovna vrsta zapisa za razumijevanje popisa
- Zapis za razumijevanje popisa s uvjetnim grananjem ako
- Kombinacija s ternarnim operatorima (ako je drugačija obrada)
zip()
,enumerate()
Kombinacija s ovim- notacija uključivanja ugniježđenog popisa
Zatim ćemo objasniti skup notacije za razumijevanje popisa s uzorkom koda.
- skup inkluzije notacije(
Set comprehensions
) - rječnik inclusion notation(
Dict comprehensions
) - tip generatora(
Generator expressions
)
- Osnovna vrsta zapisa za razumijevanje popisa
- Zapis za razumijevanje popisa s uvjetnim grananjem ako
- Kombinacija s ternarnim operatorima (ako je drugačija obrada)
- Kombinacija sa zip() i enumerate()
- notacija uključivanja ugniježđenog popisa
- skup inkluzije notacije(Set comprehensions)
- rječnik inclusion notation(Dict comprehensions)
- tip generatora(Generator expressions)
Osnovna vrsta zapisa za razumijevanje popisa
Oznaka razumijevanja popisa napisana je kako slijedi.
[Expression for Any Variable Name in Iterable Object]
Uzima svaki element iterativnog objekta kao što je popis, tuple ili raspon pomoću proizvoljnog naziva varijable i procjenjuje ga izrazom. Vraća se novi popis s rezultatom evaluacije kao elementom.
Naveden je primjer zajedno s ekvivalentom za izjavu.
squares = [i**2 for i in range(5)]
print(squares)
# [0, 1, 4, 9, 16]
squares = []
for i in range(5):
squares.append(i**2)
print(squares)
# [0, 1, 4, 9, 16]
Isti se proces može učiniti s mapom(), ali je notacija shvaćanja popisa poželjna zbog svoje jednostavnosti i jasnoće.
Zapis za razumijevanje popisa s uvjetnim grananjem ako
Moguće je i uvjetno grananje s if. Upišite if u postfiks na sljedeći način.
[Expression for Any Variable Name in Iterable Object if Conditional Expression]
Izrazom se evaluiraju samo elementi iterativnog objekta čiji je uvjetni izraz istinit, a vraća se novi popis čiji su elementi rezultat.
U uvjetnom izrazu možete koristiti bilo koje ime varijable.
Naveden je primjer zajedno s ekvivalentom za izjavu.
odds = [i for i in range(10) if i % 2 == 1]
print(odds)
# [1, 3, 5, 7, 9]
odds = []
for i in range(10):
if i % 2 == 1:
odds.append(i)
print(odds)
# [1, 3, 5, 7, 9]
Isti se proces može učiniti s filter(), ali je notacija za razumijevanje popisa poželjna zbog svoje jednostavnosti i jasnoće.
Kombinacija s ternarnim operatorima (ako je drugačija obrada)
U gornjem primjeru obrađuju se samo oni elementi koji zadovoljavaju kriterije, a oni koji ne zadovoljavaju kriterije isključeni su iz novog popisa.
Ako želite promijeniti proces ovisno o uvjetu, ili ako želite obraditi elemente koji ne zadovoljavaju uvjet drugačije, kao u if else, koristite ternarni operator.
U Pythonu se ternarni operator može napisati na sljedeći način
Value When True if Conditional Expression else Value When False
Ovo se koristi u dijelu izraza u zapisu o razumijevanju popisa kao što je prikazano u nastavku.
[Value When True if Conditional Expression else Value When False for Any Variable Name in Iterable Object]
Naveden je primjer zajedno s ekvivalentom za izjavu.
odd_even = ['odd' if i % 2 == 1 else 'even' for i in range(10)]
print(odd_even)
# ['even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd']
odd_even = []
for i in range(10):
if i % 2 == 1:
odd_even.append('odd')
else:
odd_even.append('even')
print(odd_even)
# ['even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd']
Također je moguće pisati izraze koristeći proizvoljne nazive varijabli za istinite i netočne vrijednosti.
Ako je uvjet zadovoljen, neka obrada se obavlja, u protivnom vrijednost originalnog iterable objekta ostaje nepromijenjena.
odd10 = [i * 10 if i % 2 == 1 else i for i in range(10)]
print(odd10)
# [0, 10, 2, 30, 4, 50, 6, 70, 8, 90]
Kombinacija sa zip() i enumerate()
Korisne funkcije koje se često koriste u izrazu for uključuju zip(), koji kombinira višestruke iterable, i enumerate(), koji vraća vrijednost zajedno sa svojim indeksom.
Naravno, moguće je koristiti zip() i enumerate() s notacijom razumijevanja popisa. To nije posebna sintaksa i nije teško ako uzmete u obzir korespondenciju s naredbom for.
Primjer zip().
l_str1 = ['a', 'b', 'c']
l_str2 = ['x', 'y', 'z']
l_zip = [(s1, s2) for s1, s2 in zip(l_str1, l_str2)]
print(l_zip)
# [('a', 'x'), ('b', 'y'), ('c', 'z')]
l_zip = []
for s1, s2 in zip(l_str1, l_str2):
l_zip.append((s1, s2))
print(l_zip)
# [('a', 'x'), ('b', 'y'), ('c', 'z')]
Primjer enumerate().
l_enu = [(i, s) for i, s in enumerate(l_str1)]
print(l_enu)
# [(0, 'a'), (1, 'b'), (2, 'c')]
l_enu = []
for i, s in enumerate(l_str1):
l_enu.append((i, s))
print(l_enu)
# [(0, 'a'), (1, 'b'), (2, 'c')]
Ideja je ista kao i prije kada se koristi if.
l_zip_if = [(s1, s2) for s1, s2 in zip(l_str1, l_str2) if s1 != 'b']
print(l_zip_if)
# [('a', 'x'), ('c', 'z')]
Svaki element se također može koristiti za izračunavanje novog elementa.
l_int1 = [1, 2, 3]
l_int2 = [10, 20, 30]
l_sub = [i2 - i1 for i1, i2 in zip(l_int1, l_int2)]
print(l_sub)
# [9, 18, 27]
notacija uključivanja ugniježđenog popisa
Poput ugniježđenja za petlje, zapis razumijevanja popisa također može biti ugniježđen.
[Expression for Variable Name 1 in Iterable Object 1
for Variable Name 2 in Iterable Object 2
for Variable Name 3 in Iterable Object 3 ... ]
Radi praktičnosti, dodani su prijelomi redaka i uvlačenja, ali nisu potrebni za gramatiku; mogu se nastaviti na jednom redu.
Naveden je primjer zajedno s ekvivalentom za izjavu.
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [x for row in matrix for x in row]
print(flat)
# [1, 2, 3, 4, 5, 6, 7, 8, 9]
flat = []
for row in matrix:
for x in row:
flat.append(x)
print(flat)
# [1, 2, 3, 4, 5, 6, 7, 8, 9]
Također je moguće koristiti više varijabli.
cells = [(row, col) for row in range(3) for col in range(2)]
print(cells)
# [(0, 0), (0, 1), (1, 0), (1, 1), (2, 0), (2, 1)]
Također možete napraviti uvjetno grananje.
cells = [(row, col) for row in range(3)
for col in range(2) if col == row]
print(cells)
# [(0, 0), (1, 1)]
Također je moguće uvjetno granati za svaki iterable objekt.
cells = [(row, col) for row in range(3) if row % 2 == 0
for col in range(2) if col % 2 == 0]
print(cells)
# [(0, 0), (2, 0)]
skup inkluzije notacije(Set comprehensions)
Promjena uglastih zagrada [] u zapisu razumijevanja popisa u vitičaste zagrade {} stvara skup (objekt tipa skupa).
{Expression for Any Variable Name in Iterable Object}
s = {i**2 for i in range(5)}
print(s)
# {0, 1, 4, 9, 16}
rječnik inclusion notation(Dict comprehensions)
Rječnici (objekti tipa dict) također se mogu generirati s notacijom razumijevanja.
{} i navedite ključ i vrijednost u dijelu izraza kao ključ: vrijednost.
{Key: Value for Any Variable Name in Iterable Object}
Za ključ i vrijednost može se odrediti bilo koji izraz.
l = ['Alice', 'Bob', 'Charlie']
d = {s: len(s) for s in l}
print(d)
# {'Alice': 5, 'Bob': 3, 'Charlie': 7}
Za izradu novog rječnika s popisa ključeva i vrijednosti, koristite funkciju zip().
keys = ['k1', 'k2', 'k3']
values = [1, 2, 3]
d = {k: v for k, v in zip(keys, values)}
print(d)
# {'k1': 1, 'k2': 2, 'k3': 3}
tip generatora(Generator expressions)
Ako se uglaste zagrade [] u zapisu shvaćanja popisa koriste kao okrugle zagrade (), umjesto torke vraća se generator. To se naziva generatorskim izrazima.
Primjer bilježenja za razumijevanje popisa.
l = [i**2 for i in range(5)]
print(l)
# [0, 1, 4, 9, 16]
print(type(l))
# <class 'list'>
Primjer generatorskog izraza. Ako ispišete() generator kakav jest, on neće ispisati njegov sadržaj, ali ako ga pokrenete s for naredbom, možete dobiti sadržaj.
g = (i**2 for i in range(5))
print(g)
# <generator object <genexpr> at 0x10af944f8>
print(type(g))
# <class 'generator'>
for i in g:
print(i)
# 0
# 1
# 4
# 9
# 16
Izrazi generatora također dopuštaju uvjetno grananje i ugniježđenje korištenjem if kao i notacije razumijevanja popisa.
g_cells = ((row, col) for row in range(0, 3)
for col in range(0, 2) if col == row)
print(type(g_cells))
# <class 'generator'>
for i in g_cells:
print(i)
# (0, 0)
# (1, 1)
Na primjer, ako se popis s velikim brojem elemenata generira pomoću zapisa za razumijevanje popisa, a zatim se prođe kroz naredbu for, popis koji sadrži sve elemente bit će generiran na početku ako se koristi zapis razumijevanja popisa. S druge strane, ako koristite izraz generatora, svaki put kada se petlja ponavlja, elementi se generiraju jedan po jedan, čime se smanjuje količina korištene memorije.
Ako je izraz generatora jedini argument funkcije, okrugle zagrade () mogu se izostaviti.
print(sum([i**2 for i in range(5)]))
# 30
print(sum((i**2 for i in range(5))))
# 30
print(sum(i**2 for i in range(5)))
# 30
Što se tiče brzine obrade, zapis shvaćanja popisa često je brži od zapisa generatora kada se obrađuju svi elementi.
Međutim, kada se prosuđuje pomoću all() ili any(), na primjer, rezultat se određuje kada je prisutan false ili true, tako da korištenje izraza generatora može biti brže nego korištenje zapisa za razumijevanje popisa.
Ne postoji notacija razumijevanja tuple, ali ako koristite izraz generatora kao argument tuple(), možete generirati tuple u notaciji razumijevanja.
t = tuple(i**2 for i in range(5))
print(t)
# (0, 1, 4, 9, 16)
print(type(t))
# <class 'tuple'>