← Přehled všech hodin

Seznamy a inventář

Cíl hodiny: Naučíš se uložit víc hodnot do jedné proměnné a dostat se na konkrétní prvek a seznam měnit.
Jak stránku používat: vpravo nahoře je tlačítko Prezentace — schová všechno kromě jednoho bloku a přepíná se šipkami. U ukázek a cvičení je kód vlevo editovatelný: uprav ho a klikni na Spustit (nebo Ctrl+Enter), výsledek se objeví vpravo. Běží to přímo v prohlížeči, bez instalace.

1. Pochopení tématu

Blok 1Proč seznam vůbec potřebujeme1. Pochopení tématu

Začni problémem, ne řešením. Napiš:

A co když hrdina najde čtvrtou věc? A dvacátou? Budeš psát dvacet proměnných? A jak zjistíš, kolik jich má? A jak jednu vyhodíš?

Tohle je bolest, kterou seznam řeší.

Seznam je jedna proměnná, do které se vejde libovolně mnoho hodnot. Jako batoh: má jedno jméno, ale uvnitř je věcí kolik chceš.

Blok 2Index a proč se počítá od nuly1. Pochopení tématu

Index není „kolikátá věc", ale „o kolik kroků od začátku". První věc je na začátku, takže nula kroků. Proto [0].

Pomůže jednoduchý náčrt řady krabiček s čísly nad nimi.

Časté chyby:

inventar[3]    # IndexError - seznam má jen indexy 0,1,2

Když má seznam tři věci, poslední index je dvojka, ne trojka. Poslední index je vždycky len(seznam) - 1. Nebo prostě použij [-1].

Blok 3Základní operace1. Pochopení tématu

remove řekne co smazat. pop řekne odkud vzít — a ještě ti to podá do ruky. Rozdíl je jako mezi „vyhoď ten meč" a „podej mi, co je nahoře".

Důležité upozornění:

inventar.remove("kladivo")    # ValueError, když tam kladivo není

Vždycky nejdřív zkontrolovat: if "kladivo" in inventar:

Blok 4Zjišťování informací1. Pochopení tématu
len(inventar)              # kolik věcí
"meč" in inventar          # True/False
inventar.count("lektvar")  # kolikrát tam je
inventar.index("štít")     # na jaké pozici

in je nesmírně užitečné a budeš ho používat neustále.

Takto jednoduše můžeš ověřit, jestli v inventáři něco je, a podle toho reagovat.

Blok 5Řezy (slicing) — vyber si kus seznamu1. Pochopení tématu

Druhé číslo je „kam už nesahám". [0:3] znamená „ber od nuly, ale u trojky se zastav". Vypadá to divně, ale výhoda je, že [0:3] vrátí přesně 3 věci.

Blok 6Řazení a otočení1. Pochopení tématu
inventar.sort()               # seřadí NA MÍSTĚ, nic nevrací
inventar.reverse()            # otočí na místě
serazeny = sorted(inventar)   # vrátí NOVÝ seřazený, původní nechá

Pozor na past: x = inventar.sort() uloží do x hodnotu None. Metody končící na sort() a reverse() mění seznam přímo a nic nevracejí.

Blok 7Seznam čísel a užitečné funkce1. Pochopení tématu

To se hodí na statistiky souboje.

Blok 8Seznam ve Streamlitu1. Pochopení tématu

Streamlit umí seznam zobrazit několika způsoby:

st.selectbox a st.multiselect berou seznam přímo jako parametr — uvidíš výsledek hned a je to velmi praktické.

Poznámky pro učiteleTechnické pozadí pro učitele1. Pochopení tématu
  • Python list je dynamické pole (jako List<T> v C#), amortizované O(1) append, ale O(n) insert(0, ...) a remove().
  • Seznam je mutovatelný a předává se odkazem. b = a nevytvoří kopii! Kopie je b = a.copy() nebo b = a[:]. Toto dětem ukažte, až narazí na chybu.
  • V session_state je seznam uložený jako reference, takže .append() na něm funguje a změna se zachová bez nutnosti přiřazovat zpět.
Blok 9Časté chyby1. Pochopení tématu
Chyba Příčina Řešení
IndexError: list index out of range Sáhl mimo seznam Kontrolovat len()
ValueError: x not in list remove() neexistující věci Nejdřív if x in seznam
x = seznam.sort() je None sort() nic nevrací Použít sorted()
Změna v jednom seznamu se projeví v druhém b = a je odkaz b = a.copy()
IndexError na prázdném seznamu seznam[0] bez kontroly if seznam:
Seznam se pořád vyprazdňuje Inicializace bez if not in Podmíněná inicializace

2. Ukázky pro projekci

Ukázka 1 — Anatomie seznamu

demo/demo1_anatomie.py
import streamlit as st

st.title("Co je uvnitř seznamu")

inventar = ["meč", "štít", "lektvar", "klíč", "mapa"]

st.subheader("Seznam a jeho indexy")

sloupce = st.columns(len(inventar))
for i, sloupec in enumerate(sloupce):
    sloupec.metric(f"[{i}]", inventar[i])
    sloupec.caption(f"[-{len(inventar) - i}]")

st.divider()

st.subheader("Vyzkoušej si index")
index = st.slider("index", -len(inventar), len(inventar) - 1, 0)
st.code(f"inventar[{index}]  ->  {inventar[index]!r}")

st.divider()

st.subheader("Užitečné informace")
st.code(
    f"len(inventar)          ->  {len(inventar)}\n"
    f"'klíč' in inventar     ->  {'klíč' in inventar}\n"
    f"'luk' in inventar      ->  {'luk' in inventar}\n"
    f"inventar.index('štít') ->  {inventar.index('štít')}\n"
    f"inventar[-1]           ->  {inventar[-1]!r}"
)

Ukázka 2 — Řezy naživo

demo/demo2_rezy.py
import streamlit as st

st.title("Řezy seznamu")

inventar = ["meč", "štít", "lektvar", "klíč", "mapa", "lano"]

st.write("Původní seznam:", inventar)

od, do = st.slider(
    "Vyber rozsah [od:do]",
    0, len(inventar), (1, 4)
)

st.code(f"inventar[{od}:{do}]  ->  {inventar[od:do]}")
st.write(f"Počet vybraných: **{len(inventar[od:do])}**")

st.divider()

st.subheader("Hotové příklady")
st.code(
    f"inventar[:3]   ->  {inventar[:3]}\n"
    f"inventar[3:]   ->  {inventar[3:]}\n"
    f"inventar[-2:]  ->  {inventar[-2:]}\n"
    f"inventar[::2]  ->  {inventar[::2]}   (každý druhý)\n"
    f"inventar[::-1] ->  {inventar[::-1]}  (pozpátku)"
)

Ukázka 3 — Živý inventář

demo/demo3_inventar.py
import streamlit as st

st.set_page_config(page_title="Inventář", page_icon="🎒")
st.title("🎒 Inventář hrdiny")

if "inventar" not in st.session_state:
    st.session_state.inventar = ["meč", "lektvar"]

NALEZY = ["štít", "klíč", "mapa", "lano", "lektvar", "prsten"]

a, b = st.columns(2)

with a:
    st.subheader("Přidat")
    vec = st.selectbox("Co jsi našel?", NALEZY)
    if st.button("➕ Sebrat"):
        st.session_state.inventar.append(vec)
        st.rerun()

with b:
    st.subheader("Vyhodit")
    if st.session_state.inventar:
        k_vyhozeni = st.selectbox("Co vyhodíš?", st.session_state.inventar)
        if st.button("➖ Vyhodit"):
            st.session_state.inventar.remove(k_vyhozeni)
            st.rerun()
    else:
        st.caption("Batoh je prázdný.")

st.divider()

inv = st.session_state.inventar
st.subheader(f"Obsah batohu ({len(inv)} věcí)")

if inv:
    for i, v in enumerate(inv):
        st.write(f"**[{i}]** {v}")
else:
    st.info("Batoh je prázdný.")

st.divider()
st.code(
    f"len(inventar)      ->  {len(inv)}\n"
    f"'klíč' in inventar ->  {'klíč' in inv}\n"
    f"seřazeně           ->  {sorted(inv)}"
)

3. Cvičení na hodinu

Blok 10Cvičení 1 — Seznam kouzel (15 min)3. Cvičení na hodinu

Tvoje zadání:

  1. Vytvoř seznam pěti kouzel, například ["Ohnivá koule", "Blesk", "Léčení", "Štít", "Neviditelnost"]
  2. Vypiš kolik kouzel hrdina umí pomocí len()
  3. Vypiš první a poslední kouzlo (použij [0] a [-1])
  4. Přidej st.selectbox, kterým si uživatel kouzlo vybere
  5. Podle vybraného kouzla vypiš jeho index a jinou hlášku
Úroveň Co má zvládnout
Minimum Body 1–4
Rozšíření Bod 5 + vypsat, jestli je kouzlo v první polovině seznamu
Výzva Přidat druhý seznam s manou a spárovat je podle indexu
cviceni/cviceni1_kouzla.py
Tady se objeví výsledekKlikni na Spustit. Kód vlevo můžeš měnit a spouštět opakovaně klávesami Ctrl+Enter.
Kód vlevo jde upravovat. Tab odsazuje o čtyři mezery.
Tip — na co si dát pozor

Očekávaný výsledek: výběr kouzla ukáže jeho pořadí i popis.

Řešení 1 — jedna z možných variant
reseni/reseni1_kouzla.py
Tady se objeví výsledekKlikni na Spustit. Kód vlevo můžeš měnit a spouštět opakovaně klávesami Ctrl+Enter.
Kód vlevo jde upravovat. Tab odsazuje o čtyři mezery.
Blok 11Cvičení 2 — Batoh s limitem (20 min)3. Cvičení na hodinu

Tvoje zadání:

  1. Ulož batoh do session_state jako prázdný seznam
  2. Přidej st.selectbox s nabídkou věcí a tlačítko „Sebrat"
  3. Nastav limit 5 věcí — když je batoh plný, vypiš st.error a nic nepřidávej
  4. Přidej tlačítko „Zahodit poslední" pomocí .pop()
  5. Ukaž zaplnění batohu přes st.progress
Úroveň Co má zvládnout
Minimum Body 1–3
Rozšíření Body 4–5
Výzva Nedovolit dvě stejné věci (kromě lektvarů)
cviceni/cviceni2_batoh.py
Tady se objeví výsledekKlikni na Spustit. Kód vlevo můžeš měnit a spouštět opakovaně klávesami Ctrl+Enter.
Kód vlevo jde upravovat. Tab odsazuje o čtyři mezery.
Tip — na co si dát pozor

Očekávaný výsledek: batoh se plní, po pěti věcech odmítá další.

Řešení 2 — jedna z možných variant
reseni/reseni2_batoh.py
Tady se objeví výsledekKlikni na Spustit. Kód vlevo můžeš měnit a spouštět opakovaně klávesami Ctrl+Enter.
Kód vlevo jde upravovat. Tab odsazuje o čtyři mezery.
Blok 12Cvičení 3 — Statistiky soubojů (20 min)3. Cvičení na hodinu

Tvoje zadání:

  1. Vytvoř v session_state seznam zraneni = []
  2. Přidej st.number_input a tlačítko „Zapsat zranění"
  3. Když je v seznamu aspoň jedno číslo, spočítej součet, největší, nejmenší a průměr
  4. Zobraz je pomocí čtyř st.metric ve sloupcích
  5. Přidej st.bar_chart(zraneni) — uvidí graf svých soubojů
Úroveň Co má zvládnout
Minimum Body 1–3
Rozšíření Body 4–5
Výzva Vypsat, kolikrát byl zásah nadprůměrný
cviceni/cviceni3_statistiky.py
Tady se objeví výsledekKlikni na Spustit. Kód vlevo můžeš měnit a spouštět opakovaně klávesami Ctrl+Enter.
Kód vlevo jde upravovat. Tab odsazuje o čtyři mezery.
Tip — na co si dát pozor

Očekávaný výsledek: graf roste s každým zápisem, statistiky se přepočítávají.

Řešení 3 — jedna z možných variant
reseni/reseni3_statistiky.py
Tady se objeví výsledekKlikni na Spustit. Kód vlevo můžeš měnit a spouštět opakovaně klávesami Ctrl+Enter.
Kód vlevo jde upravovat. Tab odsazuje o čtyři mezery.
Blok 13Cvičení 4 — Řazení družiny (20 min)3. Cvičení na hodinu

Tvoje zadání:

  1. Vytvoř seznam jmen členů družiny (aspoň 6)
  2. Přidej st.radio s možnostmi „Původní / Abecedně / Pozpátku"
  3. Podle volby seznam seřaď (pozor: sorted() vrací nový, sort() mění původní)
  4. Vypiš seřazený seznam s čísly pořadí
  5. Přidej st.multiselect na výběr, kdo jde na výpravu, a vypiš kolik jich jde
Úroveň Co má zvládnout
Minimum Body 1–4
Rozšíření Bod 5
Výzva Přidat volbu „podle délky jména" pomocí sorted(jmena, key=len)
cviceni/cviceni4_razeni.py
Tady se objeví výsledekKlikni na Spustit. Kód vlevo můžeš měnit a spouštět opakovaně klávesami Ctrl+Enter.
Kód vlevo jde upravovat. Tab odsazuje o čtyři mezery.
Tip — na co si dát pozor

Očekávaný výsledek: stejný seznam se zobrazuje v různých pořadích.

Řešení 4 — jedna z možných variant
reseni/reseni4_razeni.py
Tady se objeví výsledekKlikni na Spustit. Kód vlevo můžeš měnit a spouštět opakovaně klávesami Ctrl+Enter.
Kód vlevo jde upravovat. Tab odsazuje o čtyři mezery.
Blok 14Cvičení 5 — PyQuest: inventář ve hře (25 min)3. Cvičení na hodinu

Tvoje zadání:

  1. Přidej do hry inventar v session_state s výchozím obsahem ["meč"]
  2. Po úspěšné výpravě přidej do inventáře odměnu podle místa (Les → lano, Jeskyně → klíč, Věž → prsten)
  3. Zobraz inventář v postranním panelu
  4. Do Věže pusť hrdinu jen tehdy, když má v inventáři "klíč"
  5. Přidej tlačítko „Prodat vše" — každá věc dá 20 zlata a inventář se vyprázdní
Úroveň Co má zvládnout
Minimum Body 1–3
Rozšíření Bod 4 s kontrolou in
Výzva Bod 5 + různé ceny pro různé věci
cviceni/cviceni5_pyquest_inventar.py
Tady se objeví výsledekKlikni na Spustit. Kód vlevo můžeš měnit a spouštět opakovaně klávesami Ctrl+Enter.
Kód vlevo jde upravovat. Tab odsazuje o čtyři mezery.
Tip — na co si dát pozor

Očekávaný výsledek: hra má funkční ekonomiku a postup blokovaný předmětem.

Řešení 5 — jedna z možných variant
reseni/reseni5_pyquest_inventar.py
Tady se objeví výsledekKlikni na Spustit. Kód vlevo můžeš měnit a spouštět opakovaně klávesami Ctrl+Enter.
Kód vlevo jde upravovat. Tab odsazuje o čtyři mezery.

4. Domácí úkol

Blok 15Domácí úkol na příští hodinu4. Domácí úkol

Přidej do hry obchod: seznam nabízeného zboží a tlačítko na koupi. Koupená věc se přidá do inventáře a odečte zlato. Nedovol koupit, když hrdina nemá dost zlata nebo když už věc má.

Zobrazit ukázkové řešení domácího úkolu

Toto je jedna z možných variant, jak mohl úkol dopadnout. Tvoje řešení se může lišit a to je v pořádku.

domaci/domaci_ukol06.py
Tady se objeví výsledekKlikni na Spustit. Kód vlevo můžeš měnit a spouštět opakovaně klávesami Ctrl+Enter.
Kód vlevo jde upravovat. Tab odsazuje o čtyři mezery.
Blok 16Oficiální dokumentace4. Domácí úkol

Oficiální dokumentace se hodí ve chvíli, kdy si chceš ověřit práci se seznamem, zjistit další užitečné metody nebo si připomenout, jak fungují řezy a indexy. U Streamlitu se pak vyplatí mrknout na widgety, které umí seznam použít přímo.

Co jsme použili Oficiální dokumentace Co tam najdeš
seznam list Sequence types — list, tuple, range základy seznamů, indexování i běžné operace
append() list.append přidávání položek na konec seznamu
remove() list.remove mazání položky podle hodnoty
pop() list.pop odebrání a vrácení položky ze seznamu
len() len zjištění počtu prvků
operátor in Common sequence operations test, jestli položka v seznamu je
řezy seznam[a:b] Slicings výběr části seznamu pomocí rozsahu
sorted() a sort() sorted, list.sort řazení seznamu dvěma způsoby
st.selectbox st.selectbox výběr jedné položky ze seznamu
st.multiselect st.multiselect výběr více položek najednou
enumerate() enumerate průchod seznamem spolu s indexy

5. Umíme informatiku

Blok 17Navazující cvičení na Umíme informatiku5. Umíme informatiku
Cvičení Odkaz Proč se hodí
Programování v Pythonu umimeinformatiku.cz Práce se seznamy
Tabulky umimeinformatiku.cz Data v řadách a sloupcích
Robotanik umimeinformatiku.cz Posloupnosti kroků
Úkolovka umimeinformatiku.cz Seznam úkolů