get, keys/values/items, seznam slovníků, vnořováníNejdřív se podívej na slabinu seznamu:
Co je to třicítka? Životy? Síla? Zlato? Musíš si pamatovat pořadí. A když někdo mezi to vloží další údaj, celý program se rozbije.
Seznam si pamatuje pořadí. Slovník si pamatuje jména. Ve slovníku je jedno, v jakém pořadí to napíšeš.
Analogie: seznam je řada čísel dveří, slovník je jmenovka na dveřích.
Zásadní rozdíl proti seznamu: u slovníku vytvoří přiřazení nový klíč,
u seznamu by seznam[5] = x na neexistujícím indexu spadlo.
prisera["sila"] # KeyError, když klíč neexistuje!
prisera.get("sila") # None, nespadne
prisera.get("sila", 5) # 5 - výchozí hodnota
getje opatrná varianta. Když klíč není, nespadne, ale vrátí náhradní hodnotu. Používej ji všude, kde si nejsi jistý, že klíč existuje.
Tohle je nejužitečnější věc z celé hodiny.
items()ti dá obojí najednou. To je nejpohodlnější způsob, jak slovník projít. Zápis se dvěma proměnnými poforznamená „rozbal mi tu dvojici".
Velmi častý a užitečný vzor — nahrazuje dlouhé if/elif:
# Místo tohohle:
if misto == "Les":
nebezpeci = 20
elif misto == "Jeskyně":
nebezpeci = 45
elif misto == "Věž":
nebezpeci = 70
# Napiš tohle:
NEBEZPECI = {"Les": 20, "Jeskyně": 45, "Věž": 70}
nebezpeci = NEBEZPECI[misto]
Když máš spoustu podmínek, které jen přiřazují hodnotu, nahraď je slovníkem. Je to kratší, přehlednější a přidání dalšího místa je jeden řádek.
Navíc klíče slovníku jdou rovnou do selectbox.
Tohle je základ všech skutečných dat.
Seznam drží víc příšer, každý slovník popisuje jednu. Tak vypadají data v každé opravdové hře i aplikaci.
Pozor na uvozovky uvnitř f-stringu: f"{p['jmeno']}" — uvnitř dvojitých použij jednoduché.
Čte se to zleva doprava jako cesta: nejdřív „hrdina", pak z něj „životy".
st.dataframe(seznam_slovniku) udělá hotovou tabulku — výsledek uvidíš okamžitě.
dict je hashovací tabulka, vyhledání podle klíče je O(1) bez ohledu na velikost.
Analogie v C#: Dictionary<string, object>.str, int, tuple). Seznam jako klíč být nemůže.dict je mutovatelný a předává se odkazem — stejná past jako u seznamů.
Kopie: d.copy() (mělká) nebo copy.deepcopy(d) (hluboká, u vnořených dat nutná).| Chyba | Příčina | Řešení |
|---|---|---|
KeyError: 'sila' |
Klíč neexistuje | .get("sila", 0) |
TypeError: unhashable type: 'list' |
Seznam jako klíč | Použít text nebo tuple |
SyntaxError v f-stringu |
Stejné uvozovky | f"{p['jmeno']}" |
| Změna se projeví i jinde | Slovník je odkaz | .copy() |
dict místo list v selectboxu |
Chybí list() |
list(d.keys()) |
| Zapomenutá dvojtečka | {"a" 1} |
{"a": 1} |
import streamlit as st
st.title("Seznam vs. slovník")
levy, pravy = st.columns(2)
with levy:
st.subheader("📋 Seznam")
prisera_l = ["Skřet", 30, 8, 25]
st.code(str(prisera_l))
st.write("Co je co?")
st.code(
"prisera[0] -> 'Skřet'\n"
"prisera[1] -> 30 ??\n"
"prisera[2] -> 8 ??\n"
"prisera[3] -> 25 ??"
)
st.error("Musíš si pamatovat pořadí.")
with pravy:
st.subheader("🗂️ Slovník")
prisera_s = {"jmeno": "Skřet", "zivoty": 30, "sila": 8, "zlato": 25}
st.json(prisera_s)
st.code(
"prisera['jmeno'] -> 'Skřet'\n"
"prisera['zivoty'] -> 30\n"
"prisera['sila'] -> 8\n"
"prisera['zlato'] -> 25"
)
st.success("Klíč ti řekne, co to je.")
st.divider()
st.subheader("Vyzkoušej klíč")
klic = st.selectbox("Který klíč přečteme?", list(prisera_s.keys()))
st.code(f"prisera['{klic}'] -> {prisera_s[klic]!r}")
st.divider()
st.subheader("Bezpečné čtení pomocí get()")
neexistujici = st.text_input("Zkus napsat klíč, který neexistuje", "obrana")
st.code(
f"prisera['{neexistujici}'] -> KeyError 💥\n"
f"prisera.get('{neexistujici}') -> {prisera_s.get(neexistujici)}\n"
f"prisera.get('{neexistujici}', 0) -> {prisera_s.get(neexistujici, 0)}"
)
import streamlit as st
st.set_page_config(page_title="Bestiář", page_icon="👹")
st.title("👹 Bestiář")
PRISERY = [
{"jmeno": "Skřet", "zivoty": 30, "sila": 8, "zlato": 25, "emoji": "👺"},
{"jmeno": "Vlk", "zivoty": 20, "sila": 12, "zlato": 15, "emoji": "🐺"},
{"jmeno": "Kostlivec","zivoty": 40, "sila": 10, "zlato": 40, "emoji": "💀"},
{"jmeno": "Trol", "zivoty": 80, "sila": 18, "zlato": 90, "emoji": "🧌"},
{"jmeno": "Drak", "zivoty": 200, "sila": 40, "zlato": 500, "emoji": "🐉"},
]
st.subheader("Celá tabulka jedním příkazem")
st.dataframe(PRISERY, use_container_width=True)
st.caption("st.dataframe(PRISERY) - Streamlit si tabulku poskládá sám.")
st.divider()
jmena = []
for p in PRISERY:
jmena.append(p["jmeno"])
vybrane = st.selectbox("Kterou příšeru prozkoumáš?", jmena)
# najdeme slovník podle jména
nalezena = None
for p in PRISERY:
if p["jmeno"] == vybrane:
nalezena = p
if nalezena:
st.header(f"{nalezena['emoji']} {nalezena['jmeno']}")
a, b, c = st.columns(3)
a.metric("❤️ Životy", nalezena["zivoty"])
b.metric("💪 Síla", nalezena["sila"])
c.metric("💰 Zlato", nalezena["zlato"])
st.progress(min(nalezena["sila"] / 40, 1.0))
st.json(nalezena)
import streamlit as st
st.title("Slovník nahradí if/elif")
MISTA = {
"Les": {"nebezpeci": 20, "odmena": 30, "emoji": "🌲", "korist": "lano"},
"Jeskyně": {"nebezpeci": 45, "odmena": 80, "emoji": "🕳️", "korist": "klíč"},
"Věž": {"nebezpeci": 70, "odmena": 200, "emoji": "🏰", "korist": "prsten"},
"Bažina": {"nebezpeci": 55, "odmena": 120, "emoji": "🐊", "korist": "amulet"},
}
st.code(
"# Místo 8 řádků if/elif stačí:\n"
"data = MISTA[misto]\n"
"nebezpeci = data['nebezpeci']"
)
st.divider()
misto = st.selectbox("Kam půjdeš?", list(MISTA.keys()))
data = MISTA[misto]
st.header(f"{data['emoji']} {misto}")
a, b, c = st.columns(3)
a.metric("⚠️ Nebezpečí", data["nebezpeci"])
b.metric("💎 Odměna", data["odmena"])
c.metric("🎁 Kořist", data["korist"])
st.divider()
st.subheader("Všechna místa najednou")
for nazev, info in MISTA.items():
st.write(
f"{info['emoji']} **{nazev}** — nebezpečí {info['nebezpeci']}, "
f"odměna {info['odmena']} zlata, kořist: {info['korist']}"
)
Tvoje zadání:
- Vytvoř slovník
priseras klíči jmeno, zivoty, sila, zlato a emoji- Vypiš každý údaj zvlášť pomocí f-stringu
- Zobraz životy a sílu pomocí
st.metricve sloupcích- Přidej
st.selectboxs klíči slovníku a vypiš vybranou hodnotu- Ukaž rozdíl mezi
prisera["neco"]aprisera.get("neco", "nemá")
| Úroveň | Co má zvládnout |
|---|---|
| Minimum | Body 1–3 |
| Rozšíření | Bod 4 s list(prisera.keys()) |
| Výzva | Bod 5 + procházení přes .items() a výpis celé karty cyklem |
Očekávaný výsledek: karta příšery se všemi údaji.
Tvoje zadání:
- Vytvoř slovník
CENYs aspoň šesti předměty a jejich cenami- Přidej
st.selectboxs klíči a zobraz cenu vybraného předmětu- Přidej
st.number_inputna počet kusů a spočítej celkovou cenu- Vypiš celý ceník cyklem přes
.items()zarovnaný f-stringem- Přidej slevu 10 % při nákupu tří a více kusů
| Úroveň | Co má zvládnout |
|---|---|
| Minimum | Body 1–3 |
| Rozšíření | Bod 4 |
| Výzva | Bod 5 + najít nejdražší předmět pomocí max(CENY, key=CENY.get) |
Očekávaný výsledek: funkční ceník s výpočtem ceny nákupu.
Tvoje zadání:
- Vytvoř seznam aspoň čtyř slovníků popisujících příšery
- Zobraz je jako tabulku pomocí
st.dataframe- Přidej
st.sliderna maximální sílu a vypiš jen příšery slabší než limit- Spočítej, kolik příšer prošlo filtrem a jaké je jejich celkové zlato
- Přidej formulář na přidání vlastní příšery do session_state
| Úroveň | Co má zvládnout |
|---|---|
| Minimum | Body 1–2 |
| Rozšíření | Body 3–4 s cyklem a podmínkou |
| Výzva | Bod 5 s st.form |
Očekávaný výsledek: filtrovatelný bestiář, který se dá rozšiřovat.
Tvoje zadání:
- Nahraď jednotlivé proměnné hrdiny jedním slovníkem v
session_state- Klíče: jmeno, zivoty, zlato, uroven, zkusenosti
- Přidej tlačítko „Získat zkušenosti (+25)"
- Když zkušenosti přesáhnou 100, zvyš úroveň a odečti 100
- Vypiš celého hrdinu pomocí
st.jsona.items()
| Úroveň | Co má zvládnout |
|---|---|
| Minimum | Body 1–3 |
| Rozšíření | Bod 4 s postupem na vyšší úroveň |
| Výzva | Bod 5 + přidat maximum životů rostoucí s úrovní |
Očekávaný výsledek: hrdina, který se vyvíjí a jehož data jsou na jednom místě.
Tvoje zadání:
- Přesuň všechna místa do slovníku
MISTA(nebezpeci, odmena, korist, emoji, popis)- Odstraň dlouhé
if/elifa nahraď je čtením ze slovníku- Přesuň hrdinu do jednoho slovníku
st.session_state.hrdina- Přidej
PREDMETYse slovníkem cen a použij ho v obchodu- Zobraz přehled všech míst tabulkou pomocí
st.dataframe
| Úroveň | Co má zvládnout |
|---|---|
| Minimum | Body 1–2 |
| Rozšíření | Body 3–4 |
| Výzva | Bod 5 + přidat páté místo bez úpravy zbytku kódu |
Očekávaný výsledek: přidání nového místa je jeden řádek ve slovníku.
Vytvoř slovník
KOUZLA, kde klíč je název kouzla a hodnota je slovník s manou, poškozením a popisem. Přidej do hry možnost seslat kouzlo, které stojí manu a udělá poškození. Nové kouzlo musí jít přidat jedním řádkem ve slovníku.
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.
Oficiální dokumentace je užitečná ve chvíli, kdy si chceš ověřit, jak se slovníky čtou, mění nebo bezpečně procházejí. Je v angličtině, ale stačí sledovat názvy metod, příklady a krátké ukázky použití.
| Co jsme použili | Oficiální dokumentace | Co tam najdeš |
|---|---|---|
dict |
dict |
co je slovník, jak fungují klíče a hodnoty |
dict.get() |
dict.get |
bezpečné čtení hodnoty i s výchozí hodnotou |
dict.keys() |
dict.keys |
získání všech klíčů slovníku |
dict.values() |
dict.values |
získání všech hodnot slovníku |
dict.items() |
dict.items |
procházení dvojic klíč–hodnota |
del |
The del statement |
mazání položek podle klíče |
in u slovníků |
Membership test operations | ověření, jestli klíč ve slovníku existuje |
st.json |
st.json |
hezký výpis slovníku nebo JSON dat |
st.dataframe |
st.dataframe |
tabulku ze seznamu slovníků |
st.selectbox |
st.selectbox |
výběr položky ze seznamu klíčů nebo názvů |
| Cvičení | Odkaz | Proč se hodí |
|---|---|---|
| Tabulky | umimeinformatiku.cz | Data jako záznamy a sloupce |
| Kódování a modelování | umimeinformatiku.cz | Reprezentace informací |
| Programování v Pythonu | umimeinformatiku.cz | Datové struktury |
| Algoritmické myšlení | umimeinformatiku.cz | Vyhledávání v datech |