Zarábaj až 6 000 € mesačne! Akreditované rekvalifikačné kurzy od 0 €. Viac informácií.
Hľadáme nové posily do ITnetwork tímu. Pozri sa na voľné pozície a pridaj sa k najagilnejšej firme na trhu - Viac informácií.

11. diel - Zoznam v Pythone

V predchádzajúcom cvičení, Riešené úlohy k 9.-10. lekciu Pythona, sme si precvičili získané skúsenosti z predchádzajúcich lekcií.

V dnešnom Python tutoriále si predstavíme zoznam. Naučíme sa ho vytvárať, prechádzať ním a pracovať s jeho položkami pomocou funkcií a metód.

Zoznam

Predstavme si, že si chceme uložiť nejaké údaje o viacerých prvkoch. Napr. chceme v pamäti uchovávať 10 čísel, hracie pole šachovnice alebo mená 50 užívateľov. Asi nám dôjde, že v programovaní existuje nejaká lepšia cesta ako začať mechanicky vytvárať premenné uzivatel1, uzivatel2 až napr. uzivatel50. Nehľadiac na to, že premenných môžeme potrebovať napríklad 1000! Ako by sa v tom potom hľadalo? Brrr, takto nie:)

Ak potrebujeme uchovávať väčšie množstvo premenných rovnakého typu, tento problém nám rieši zoznam. Môžeme si ho predstaviť ako množstvo priehradiek, kedy v každej máme uložený jeden prvok. Priehradky sú očíslované tzv. indexy, pričom prvá priehradka má index 0:

Na obrázku je vidieť zoznam ôsmich čísel - Základné konštrukcie jazyka Python - Základné konštrukcie jazyka Python

Programovacie jazyky sa veľmi líšia v tom, ako so zoznamom pracujú. V niektorých jazykoch (najmä starších, kompilovaných) nebolo možné za behu programu vytvoriť zoznam s dynamickou veľkosťou (napr. mu dať veľkosť podľa nejakej premennej). Zoznam sa musel deklarovať s konštantnou veľkosťou priamo v zdrojovom kóde. Toto sa obchádzalo tzv. pointermi a vlastnými dátovými štruktúrami, čo často viedlo k chybám pri manuálnej správe pamäte ak nestabilite programu (napr. v C++). Tieto druhy zoznamov sa často označujú ako pole. Ako vieme, Python je interpretovaný programovací jazyk, takže neposkytuje pole s pevnou veľkosťou. Namiesto toho dostávame dynamické zoznamy, do ktorých môžeme pridávať az ktorých je možné odoberať položky podľa ľubovôle.

Výhody zoznamu

Možno vás napadá, prečo sa tu zaoberáme zoznamami, keď majú evidentne mnoho obmedzení a existujú lepšie dátové štruktúry. Odpoveď je jednoduchá: zoznamy sú totiž jednoduché. Nemyslíme tým pre nás na pochopenie (to tiež), ale najmä pre Python. Rýchlo sa s nimi pracuje, pretože prvky sú v pamäti jednoducho uložené za sebou. Vďaka dynamickej povahe zoznamov v Pythone navyše nemusia všetky prvky zaberať rovnako miesta. Mnoho vstavaných funkcií a metód v Pythone sa zoznamy pracuje alebo zoznamy vracia. Ide teda o kľúčovú dátovú štruktúru.

Na hromadnú manipuláciu s prvkami zoznamu sa používajú cykly.

Práca so zoznamom

V nasledujúcich krokoch si ukážeme, ako zoznam deklarovať a ako ho naplniť vlastnými dátami.

Deklarácia a inicializácia zoznamu

Zoznam deklarujeme a inicializujeme pomocou hranatých zátvoriek:

cisla = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Slovo cisla je samozrejme názov našej premennej. Teraz teda máme zoznam desiatich hodnôt typu int v premennej cisla.

Prístup k prvkom zoznamu

K jednotlivým prvkom uloženým v zozname pristupujeme prostredníctvom indexov vo vnútri hranatých zátvoriek. Prvým indexom je vždy 0:

print(cisla[0])
cisla[5] = 50
print(cisla[5])

V konzole uvidíme výstup:

Výstup seznamu:
1
50

Vytvorenie zoznamu pomocou funkcie range()

Plniť zoznam ručne dátami by bolo príliš pracné. Poďme teda skúsiť využiť nám už známu funkciu range() a naplňme zoznam hodnotami od 1 do 10. Pretože ale funkcia range() nevracia zoznam, ale všeobecnú sekvenciu, prevedieme ju na zoznam pomocou funkcie list():

cisla = list(range(1,11))

Na vytlačenie hodnôt celého zoznamu do konzoly využijeme cyklus for (ako keď sme tlačili jednotlivé znaky reťazca):

cisla = list(range(1,11))

for cislo in cisla:
    print(cislo, end=" ")

Takto vyzerá výstup v konzole:

Výpis seznamu pomocí cyklu for:
1 2 3 4 5 6 7 8 9 10

V niektorých jazykoch má cyklus for aj variant foreach (napríklad v C#). V Pythone sa for cyklus používa na iteráciu cez prvky v kolekcii, a je teda ekvivalentom k foreach cyklu v iných jazykoch, ako je napr. C#.

Majme na pamäti, že pomocou cyklu for nie sme schopní akokoľvek editovať prvky v zozname. V každej iterácii je v cykle referencie na nemennú položku. Nasledujúci príklad teda nebude fungovať:

# Tento kód je chybný
cisla= list(range(1, 11))
for cislo in cisla:
    cislo += 1
print(cisla)

Zápis cislo += 1 je skrátená verzia zápisu cislo = cislo + 1. V Pythone sa používa úplne bežne na skrátenie operácií s premennými. Analogicky funguje aj s ostatnými operátormi (napr. -=, *=, /= atď.).

Výsledok bude stále:

Pokus o změnu v seznamu během cyklu for:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Funkcia print(cisla) vytlačí obsah zoznamu v hranatých zátvorkách.

Úprava obsahu zoznamu s range()

V predchádzajúcom príklade sme totiž zmenili iba hodnoty premenných v cykle, nie hodnoty skutočného zoznamu. Ak chceme upraviť hodnoty zoznamu v cykle, musíme k nim pristúpiť na základe ich indexov:

for i in range(len(cisla)):
    cisla[i] += 1
print(cisla)

Funkcia len() vracia počet prvkov v zozname.

Reťazcové zoznamy

Pri práci so zoznamami nie sme limitovaní používaním čísel. Založme si ručne zoznam Simpsonovcov:

simpsons = ["Homer", "Marge", "Bart", "Lisa", "Maggie"]

Na iteráciu položiek v zozname môžeme okrem funkcie range() použiť aj funkciu enumerate(). Jej výhodou je, že nám vráti ako index položky, tak aj položku samotnú:

for i, prvek in enumerate(simpsons):
    print(f"{i}: {prvek}")

Zoznamy často slúžia na ukladanie medzivýsledkov, ktoré sa potom ďalej v programe používajú. Keď nejaký výsledok potrebujeme desaťkrát, stačí ho namiesto desaťkrát spočítať iba raz a uložiť ho do zoznamu. Odtiaľ potom výsledok iba načítame.

Orezávanie

V Pythone je možné dostať len "orezanú" časť zoznamu. Syntax je podobná ako v prípade prístupu k položkám. Len upresníme viac argumentov, podobne ako pri funkcii range():

cisla = range(10)
print(list(cisla))
print(list(cisla[0:5]))
print(list(cisla[2:8]))
print(list(cisla[1:7:2]))
print(list(cisla[2:9:2]))
print(list(cisla[6:]))

Varianty argumentov:

  • nazev_seznamu[m] vyberie jediný prvok.
  • nazev_seznamu[m:n] vyberie prvky v rozsahu mn-1 (prvok n už zahrnutý nie je).
  • nazev_seznamu[m:n:i] vyberie m a každý i-tý prvok do n-1.
Jednotlivé argumenty, ktoré určujú, čo chceme vybrať, je možné aj vynechať. Môžeme teda napísať [::2], čo nám vyberie každý druhý prvok v zozname.

Ak nie je zadaný prvý prvok, berie sa od začiatku zoznamu (index 0). Ak nie je zadaný druhý prvok, berie sa koniec zoznamu. A ak nie je zadané, o koľko prvkov chceme postupovať, je východiskový 1, teda sa vezme každý prvok v zadanom intervale. Pokiaľ nie je uvedený prvý prvok, automaticky sa začína od začiatku zoznamu (index 0). Pokiaľ nie je uvedený druhý prvok, výber pokračuje až do konca zoznamu. Pokiaľ nie je špecifikované, o koľko prvkov sa má postupovať, východisková hodnota je 1, čo znamená, že sa vyberá každý prvok v zadanom intervale.

Metódy a funkcie pre prácu so zoznamami

Základné operácie so zoznamami v Pythone sme si už predstavili. Teraz sa zameriame na prehĺbenie našich zručností s využitím rôznych metód a funkcií, ktoré Python pre efektívnu a flexibilnú manipuláciu so zoznamami ponúka. Umožňujú nám vykonávať operácie ako triedenie, invertovanie, pridávanie alebo odstraňovanie prvkov a mnoho ďalšieho. S týmito nástrojmi sa stáva práca so zoznamami v Pythone oveľa jednoduchšia a intuitívnejšia.

Metódy pre prácu so zoznamami

Existuje mnoho metód určených priamo pre prácu so zoznamami. Poďme sa pozrieť na tie najpoužívanejšie. Jednotlivé metódy si predstavíme postupne a uvedieme si aj jednoduché príklady.

Metóda append()

Metóda append() vloží novú položku na koniec zoznamu:

cisla = [2, 3, 16, 21]
cisla.append(13)
print(cisla)

Metóda insert()

Metóda insert() vloží novú položku na konkrétny index v zozname. Prvým parametrom metódy je index, na ktorý chceme vložiť novú položku. Druhým parametrom je samotná položka:

cisla = [2, 3, 16, 21]
cisla.insert(1, 10)
print(cisla)

Metóda extend()

Metóda extend() pripojí všetky položky z danej sekvencie do zoznamu:

cisla = [2, 3, 16, 21]
dalsi_cisla = [13, 18, 24]
cisla.extend(dalsi_cisla)
print(cisla)

Metóda clear()

Metóda clear() odoberie všetky položky zo zoznamu. Rovnaký výsledok môžeme dosiahnuť zápisom del seznam[:]:

cisla = [2, 3, 16, 21]
cisla.clear()
print(cisla)

Metóda remove()

Metóda remove() odoberie danú položku zo zoznamu. V prípade, že hľadaná položka nie je v zozname nájdená, metóda remove() vyvolá výnimku:

cisla = [2, 3, 16, 21]
cisla.remove(3)
print(cisla)

Metóda reverse()

Metóda reverse() otočí poradie položiek v zozname tak, že prvá položka je teraz posledná, druhá je predposledná atď.:

cisla = [2, 3, 16, 21]
cisla.reverse()
print(cisla)

Metóda count()

Metóda count() vracia počet výskytov danej položky v zozname:

cisla = [2, 3, 16, 21, 2, 2, 3]
pocet_dvojek = cisla.count(2)
print(pocet_dvojek)

Metóda sort()

Metóda sort() zoznam zoradí. Je dokonca tak múdra, že pracuje podľa toho, čo máme v zozname uložené. Textové reťazce zoradia podľa abecedy, čísla podľa veľkosti atď. Skúsme si zotriediť a vypísať našu rodinku Simpsonovcov:

simpsons = ["Homer", "Marge", "Bart", "Lisa", "Maggie"]
simpsons.sort()
for s in simpsons:
    print(s, end = " ")

Metóda index()

Metóda index() vracia index prvého výskytu hľadanej položky. Ak položka nie je nájdená, metóda vyvolá výnimku ValueError. Metóda si hľadanú položku berie ako parameter. Ďalej môžeme upresniť dva ďalšie číselné parametre, ktoré určujú počiatočný a konečný index, medzi ktorými má byť položka hľadaná. Napríklad umožníme užívateľovi zadať meno Simpsona a povieme mu, na ktorej pozícii je Simpson uložený. Teraz to pre nás nemá hlbší význam, pretože položka je iba jednoduchý string. Metóda sa nám však bude veľmi hodiť vo chvíli, keď v zozname budeme mať uložené plnohodnotné objekty. Nasledujúci príklad teda berme ako takú prípravu:

simpsons = ["Homer", "Marge", "Bart", "Lisa", "Maggie"]
simpson = input("Ahoj, zadaj svojho obľúbeného Simpsona (z rodiny Simpsonovcov): ")
if simpson in simpsons:
    pozice = simpsons.index(simpson);
    print(f"Jo, to je môj {pozice+1}. najobľúbenejšie Simpson!")
else:
    print("Hele, toto nie je Simpson!")

A v konzole vidíme:

Využití metody index():
Ahoj, zadaj svojho obľúbeného Simpsona (z rodiny Simpsonovcov): 
Bart
Jo, to je môj 3. najobľúbenejšie Simpson!

Funkcie pre prácu so zoznamami

Python tiež obsahuje niekoľko globálnych funkcií pre prácu so zoznamom. Tieto funkcie nie sú špecifické iba pre zoznamy, ale fungujú aj pri iných kolekciách alebo sekvenciách, ako sú n-tice, reťazce, množiny a slovníky.

Funkcia len()

S touto funkciou sme sa už stretli. Vracia nám počet všetkých položiek v zozname:

cisla = [2, 3, 16, 21, 2, 2, 3]
pocet_prvku = len(cisla)
print(pocet_prvku)

Funkcia min(), max(), sum()

Jedná sa o matematické funkcie:

  • min() vracia najmenšiu z položiek v zozname.
  • max() vracia najväčšiu z položiek v zozname.
  • sum() vracia súčet všetkých hodnôt položiek v zozname (pri číselných typoch).
Pozrime sa na príklad:
cisla = [5, 10, 15, 20, 25]

nejmensi = min(cisla)
print(f"Nejmenší číslo v seznamu je: {nejmensi}")

nejvetsi = max(cisla)
print(f"Největší číslo v seznamu je: {nejvetsi}")

soucet = sum(cisla)
print(f"Součet všech čísel v seznamu je: {soucet}")

Funkcia sorted()

Táto funkcia nápadne pripomína metódu sort(), ale na rozdiel od nej vracia zotriedenú kópiu pôvodného zoznamu bez toho, aby ho akokoľvek ovplyvní:

cisla = [2, 8, 1, 5, 3]
setridena_cisla = sorted(cisla)
print(f"Neuspořádaná čísla: {cisla}")
print(f"Setříděná čísla: {setridena_cisla}")

Homogénnosť zoznamov v Pythone

Zatiaľ čo v iných programovacích jazykoch bývajú zoznamy obmedzené na uchovávanie prvkov jedného dátového typu, Python nám dovoľuje vytvárať zoznamy, ktoré obsahujú rôzne dátové typy. Napríklad:

smes = [1, "Ahoj", 3.14, [1, 2, 3]]

Zoznam smes obsahuje celé číslo, reťazec, desatinné číslo a iný zoznam. Takéto zoznamy sú považované za nehomogénne. Hoci sú nehomogénne zoznamy v niektorých situáciách užitočné, často tiež spôsobujú komplikácie. Napríklad ak sa pokúsime použiť niektoré funkcie, ktoré vyžadujú homogénny zoznam (napr. funkcie určené pre prácu iba s číslami), narazíme na chyby. Keď sa chystáme treba sčítať všetky prvky v zozname, musíme sa uistiť, že všetky prvky v zozname sú čísla.

Vždy je nutné uistiť sa, že všetky prvky v zozname sú kompatibilné s operáciami, ktoré so zoznamom budeme vykonávať.

To by pre dnešok stačilo. Môžete sa so zoznamom hrať a experimentovať 😉

V nasledujúcom kvíze, Kvíz - Cykly a zoznamy v Pythone, si vyskúšame nadobudnuté skúsenosti z predchádzajúcich lekcií.


 

Predchádzajúci článok
Riešené úlohy k 9.-10. lekciu Pythona
Všetky články v sekcii
Základné konštrukcie jazyka Python
Preskočiť článok
(neodporúčame)
Kvíz - Cykly a zoznamy v Pythone
Článok pre vás napísal gcx11
Avatar
Užívateľské hodnotenie:
13 hlasov
(^_^)
Aktivity