Lekce 11 - Seznam v Pythonu
V předešlém cvičení, Řešené úlohy k 9.-10. lekci Pythonu, jsme si procvičili nabyté zkušenosti z předchozích lekcí.
V dnešním Python tutoriálu si představíme seznam. Naučíme se ho vytvářet, procházet a pracovat s jeho položkami pomocí funkcí a metod.
Seznam
Představme si, že si chceme uložit nějaké údaje o více prvcích.
Např. chceme v paměti uchovávat 10 čísel, políčka šachovnice nebo jména
50 uživatelů. Asi vám dojde, že v programování bude nějaká lepší
cesta, než začít mechanicky vytvářet proměnné uzivatel1
,
uzivatel2
, ... až uzivatel50
. Nehledě na to, že
jich můžeme potřebovat třeba 1000! A jak by se v tom potom hledalo? Brrr,
takhle ne
Pokud potřebujeme uchovávat větší množství proměnných
stejného typu, tento problém nám řeší seznam.
Můžeme si ho představit jako řadu přihrádek, kde v každé máme uložený
jeden prvek. Přihrádky jsou očíslované tzv. indexy,
přičemž první má index 0
:
(Na obrázku je vidět pole osmi čísel.)
Programovací jazyky se velmi liší v tom, jak se seznamem pracují. V některých jazycích (zejména starších, kompilovaných) nebylo možné za běhu programu vytvořit seznam s dynamickou velikostí (např. mu dát velikost dle nějaké proměnné). Seznam se musel deklarovat s konstantní velikostí přímo ve zdrojovém kódu. Toto se obcházelo tzv. pointery a vlastními datovými strukturami, což často vedlo k chybám při manuální správě paměti a nestabilitě programu (např. v C++). Tyto druhy seznamů se často označují jako pole. Jak víme, Python je interpretovaný programovací jazyk, takže neposkytuje pole s pevnou velikostí. Místo toho dostáváme dynamické seznamy, do kterých můžeme přidávat a odebírat položky podle libosti.
Výhody seznamu
Možná vás napadá, proč se tu zabýváme seznamy, když mají evidentně mnoho omezení a existují lepší datové struktury. Odpověď je prostá: seznamy jsou totiž jednoduché. Nemyslím pro nás na pochopení (to také), ale zejména pro Python. Rychle se s nimi pracuje, protože prvky jsou v paměti jednoduše uloženy za sebou. Navíc, díky dynamické povaze seznamů v Pythonu, nemusí všechny prvky zabírat stejně místa. Mnoho vestavěných funkcí a metod v Pythonu pracuje se seznamy nebo seznamy vrací. Je to klíčová datová struktura.
Pro hromadnou manipulaci s prvky seznamu se používají cykly.
Práce se seznamem
V následujících krocích si ukážeme, jak seznam deklarovat a naplnit jej vlastními daty.
Deklarace a inicializace seznamu
Seznam deklarujeme a inicializujeme pomocí hranatých závorek:
cisla = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Slovo cisla
je samozřejmě název naší proměnné. Nyní tedy
máme seznam deseti hodnot typu int
v proměnné
cisla
.
Přístup k prvkům seznamu
K jednotlivým prvkům uloženým v seznamu přistupujeme
prostřednictvím indexů uvnitř hranatých závorek, prvním
indexem je vždy 0
:
cisla = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(cisla[0])
cisla[5] = 50
print(cisla[5])
V konzoli uvidíme výstup:
Výstup seznamu:
1
50
Vytvoření seznamu pomocí
range()
Plnit seznam ručně daty by bylo příliš pracné. Pojďme tedy zkusit
využít nám již známé funkce range()
a naplňme seznam
hodnotami od 1
do 10
. Protože ale
range()
nevrací seznam, nýbrž obecnou sekvenci, převedeme ji na
seznam pomocí funkce list()
:
cisla = list(range(1,11))
K vytištění hodnot celého seznamu do konzole využijeme cyklu
for
(jako když jsme tiskli jednotlivé znaky řetězce):
cisla = list(range(1,11))
for cislo in cisla:
print(cislo, end=" ")
Takto vypadá výstup v konzoli:
Výpis seznamu pomocí cyklu for:
1 2 3 4 5 6 7 8 9 10
V některých jazycích má cyklus for
také
variantu foreach
(například v C#). V Pythonu
se for
cyklus používá pro iteraci přes prvky v kolekci, a je
tedy ekvivalentem k foreach
cyklu v jiných jazycích, jako je
C#.
Mějme na paměti, že nejsme schopni pomocí cyklu for
nijak
editovat prvky v seznamu. V každé iteraci je v cyklu reference na
neměnnou položku. Následující příklad tedy nebude
fungovat:
# Tento kód je chybný cisla= list(range(1, 11)) for cislo in cisla: cislo += 1 print(cisla)
Zápis cislo += 1
je zkrácená verze
cislo = cislo + 1
. V Pythonu se používá naprosto běžně ke
zkrácení operací s proměnnými. Analogicky funguje i s ostatními operátory
(např. -=
, *=
, /=
atd.).
Výsledek bude stále:
Pokus o změnu v seznamu během cyklu for:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Funkce print(cisla)
vytiskne obsah seznamu v
hranatých závorkách.
Úprava obsahu seznamu s
range()
V předchozím příkladu jsme totiž změnili pouze hodnoty proměnných v cyklu, nikoliv skutečného seznamu. Pakliže chceme upravit hodnoty seznamu v cyklu, musíme k nim přistoupit na základě jejich indexů:
cisla= list(range(1, 11))
for i in range(len(cisla)):
cisla[i] += 1
print(cisla)
Funkce len()
vrací počet prvků v seznamu.
Řetězcové seznamy
Při práci se seznamy nejsme limitováni jen používáním čísel. Založme si ručně seznam Simpsonů:
simpsons = ["Homer", "Marge", "Bart", "Lisa", "Maggie"]
K iteraci položek v seznamu můžeme kromě funkce range()
použít také funkci enumerate()
. Její výhodou je, že nám
vrátí jak index položky, tak i položku samotnou:
simpsons = ["Homer", "Marge", "Bart", "Lisa", "Maggie"]
for i, prvek in enumerate(simpsons):
print(f"{i}: {prvek}")
Seznamy často slouží k ukládání mezivýsledků, které se potom dále v programu používají. Když něco potřebujeme 10x, tak to nebudeme 10x počítat, ale spočítáme to jednou a uložíme do seznamu, odkud poté výsledek jen načteme.
Ořezávání
V Pythonu je možné dostat jen "ořezanou" část seznamu. Syntaxe je
podobná jako v případě přístupu k položkám. Jen upřesníme více
argumentů, podobně jako u funkce 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 argumentů jsou:
nazev_seznamu[m]
vybere jediný prvek,nazev_seznamu[m:n]
vybere prvky v rozsahum
ažn-1
(prvekn
už zahrnutý není),nazev_seznamu[m:n:i]
vyberem
a každý i-tý prvek don-1
.
Jednotlivé argumenty určující co chceme vybrat lze i vynechat. Můžeme
tedy napsat [::2]
, což nám vybere každý druhý prvek v
seznamu.
Pokud není zadaný první prvek, bere se od začátku
seznamu (index 0
) . Není-li zadaný druhý prvek, bere se
konec seznamu. A není-li zadáno, o kolik prvků chceme postupovat, je
výchozí 1
, tudíž se vezme každý prvek v zadaném
intervalu.
Metody a funkce pro práci se seznamy
Základní operace se seznamy v Pythonu jsme si již představili. Teď se zaměříme na prohloubení našich dovedností s využitím různých metod a funkcí, které Python pro efektivní a flexibilní manipulaci se seznamy nabízí. Umožňují nám provádět operace jako třídění, invertování, přidávání nebo odstraňování prvků a mnoho dalšího. S těmito nástroji se stává práce se seznamy v Pythonu mnohem jednodušší a intuitivnější.
Metody pro práci se seznamy
Existuje mnoho metod určených přímo pro práci se seznamy. Pojďme se podívat na ty nejpoužívanější. Jednotlivé metody si představíme postupně a uvedeme si také jednoduché příklady.
Metoda append()
Metoda append()
vloží novou položku na konec seznamu:
cisla = [2, 3, 16, 21]
cisla.append(13)
print(cisla)
Metoda insert()
Metoda insert()
vloží novou položku na konkrétní index v
seznamu. První parametr metody je index, na který chceme vložit novou
položku, a druhý parametr je samotná položka:
cisla = [2, 3, 16, 21]
cisla.insert(1, 10)
print(cisla)
Metoda extend()
Metoda extend()
připojí všechny položky z dané sekvence do
seznamu:
cisla = [2, 3, 16, 21]
dalsi_cisla = [13, 18, 24]
cisla.extend(dalsi_cisla)
print(cisla)
Metoda clear()
Metoda clear()
odebere všechny položky ze seznamu. Stejného
výsledku můžeme dosáhnout zápisem del seznam[:]
:
cisla = [2, 3, 16, 21]
cisla.clear()
print(cisla)
Metoda remove()
Metoda remove()
odebere danou položku ze seznamu. Tato funkce
vyvolá výjimku v případě, že
hledaná položka není v seznamu nalezena:
cisla = [2, 3, 16, 21]
cisla.remove(3)
print(cisla)
Metoda reverse()
Metoda reverse()
otočí pořadí položek v seznamu tak, že
první položka je nyní poslední, druhá je předposlední, atd:
cisla = [2, 3, 16, 21]
cisla.reverse()
print(cisla)
Metoda count()
Metoda count()
vrací počet výskytů dané položky v
seznamu:
cisla = [2, 3, 16, 21, 2, 2, 3]
pocet_dvojek = cisla.count(2)
print(pocet_dvojek)
Metoda sort()
Metoda sort()
seznam seřadí. Je dokonce tak chytrá, že
pracuje podle toho, co máme v seznamu uložené. Textové řetězce třídí
podle abecedy, čísla podle velikosti, atd. Zkusme si setřídit a vypsat naši
rodinku Simpsonů:
simpsons = ["Homer", "Marge", "Bart", "Lisa", "Maggie"]
simpsons.sort()
for s in simpsons:
print(s, end = " ")
Metoda index()
Metoda index()
vrací index prvního výskytu hledané položky.
Pokud položka není nalezena, vyvolá výjimku ValueError
. Metoda
si bere hledanou položku jako parametr. Dále můžeme upřesnit dva další
číselné parametry, určující počáteční a konečný index, mezi kterými
má být položka hledána. Umožníme například uživateli zadat jméno
Simpsona a řekneme mu, na jaké pozici je uložený. Teď to pro nás nemá
hlubší význam, protože položka jen jednoduchý string
. Bude se
nám to však velmi hodit ve chvíli, kdy v seznamu budeme mít uloženy
plnohodnotné objekty. Berme to tedy jako takovou přípravu:
simpsons = ["Homer", "Marge", "Bart", "Lisa", "Maggie"]
simpson = input("Ahoj, zadej svého oblíbeného Simpsona (z rodiny Simpsonů): ")
if simpson in simpsons:
pozice = simpsons.index(simpson);
print(f"Jo, to je můj {pozice+1}. nejoblíbenější Simpson!")
else:
print("Hele, tohle není Simpson!")
A v konzoli vidíme:
Využití metody index():
Ahoj, zadej svého oblíbeného Simpsona (z rodiny Simpsonů):
Bart
Jo, to je můj 3. nejoblíbenější Simpson!
Funkce pro práci se seznamy
Python také obsahuje několik globálních funkcí pro práci se seznamem. Tyto funkce nejsou specifické pouze pro seznamy, ale fungují také na jiných kolekcích nebo sekvencích, jako jsou n-tice, řetězce, množiny a slovníky.
Funkce len()
S touto funkcí jsme se již setkali. Vrací nám počet všech položek v seznamu:
cisla = [2, 3, 16, 21, 2, 2, 3]
pocet_prvku = len(cisla)
print(pocet_prvku)
Funkce min()
, max()
,
sum()
Jedná se o matematické funkce:
min()
vrací nejmenší z položek v seznamu,max()
vrací největší z položek v seznamu,sum()
vrací součet všech hodnot položek v seznamu (u číselných typů).
Podívejme se na pří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}")
Funkce sorted()
Tato funkce nápadně připomíná metodu sort()
, ale na rozdíl
od ní vrací setříděnou kopii původního seznamu, aniž by
jej jakkoliv ovlivnila:
cisla = [2, 8, 1, 5, 3]
setridena_cisla = sorted(cisla)
print(f"Neuspořádaná čísla: {cisla}")
print(f"Setříděná čísla: {setridena_cisla}")
Homogennost seznamů v Pythonu
Zatímco v jiných programovacích jazycích bývají seznamy omezeny na uchovávání prvků jednoho datového typu, Python nám dovoluje vytvářet seznamy, které obsahují různé datové typy. Například:
smes = [1, "Ahoj", 3.14, [1, 2, 3]]
Seznam smes
obsahuje celé číslo, řetězec, desetinné
číslo a jiný seznam. Takové seznamy jsou považovány za
nehomogenní. Ačkoli jsou nehomogenní seznamy v některých
situacích užitečné, často také působí komplikace. Například pokud se
pokusíme použít některé funkce, které vyžadují homogenní seznam (např.
funkce určené pro práci pouze s čísly), narazíme na chyby. Když se
chytáme třeba sečíst všechny prvky v seznamu, musíme se ujistit, že
všechny prvky v seznamu jsou čísla.
Vždy je nutné ujistit se, že všechny prvky v seznamu jsou kompatibilní s operacemi, které se seznamem budeme provádět.
Tak, a to už by pro dnešek stačilo. Můžete si se seznamem hrát a experimentovat 😉
V následujícím kvízu, Kvíz - Cykly a seznamy v Pythonu, si vyzkoušíme nabyté zkušenosti z předchozích lekcí.