# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# # Python Základy
#
# ## Poznámky k jupyter notebook
#
# Zachovejte <a href="https://www.python.org/dev/peps/pep-0008/">PEP8</a> za každou cenu (pokud není potřeba jinak).
#
# V jupyter notebook je možné odkazovat na objekty vytvořené v předchozích buňkách (třeba reference na třídu, nebo proměnnou). Není ale možné přistupovat k buňkám samotným (například zastavit nekonečnou smyčku).
#
# Poslední řádek v buňce se vytiskne jako výstup, pokud vrací nějaký výstup. V případě že potřebujete tisknout i jiné řádky, použijte funkci `print()`. Příklad:

print(11)

22
11

22
a = 11

22
a = 11
a

print(11)
print(a)

# ## Čísla, text a základní operace
#
# Detailní informace: https://realpython.com/python-data-types/
#
# Následuje příklad vytvoření proměnných obsahující celé číslo, reálné číslo a text.

a = 1
print(a)

b = 1.
print(b)

c = "1"
print(c)

d = True 
# d = False
print(d)

# ### type() - jak zjistit typ
# Typ proměnné je možné ověřit následovně:

type(a)

type(b)

type(c)

type(d)

type(int)

# ### Základní operace
# Následuje pár ilustrativních příkladů pro získání představy o tom jaké operace jsou možné a jaké ne:

1 + 2

1. - 2

"1" + "2"

"1" + 1

"a" - "b"

3 * 4

"abc" * 3

"já ne" + " ko" * 10 + "ktám"

3 / 2

3 // 2

3 % 2

# Code example 1.0
# output should be equal to dividend
dividend = 100
divisor = 6
result = dividend // divisor
leftover = dividend % divisor
result * divisor + leftover 

3**2

3**(1/2)

3**1/2

# Pozor, `bool` variable se chová jako číslo: `True` ~ 1, `False` ~ 0.

True + 1

True - 1

False + 1

True * 2

# !!!
True + "abc"

# Provádění některých operací s proměnnou `in place` je možné následovně:

a = 1
print(a)
a += 2
print(a)
a *= 3
print(a)
a -= 10
print(a)

# ### Indexování, slicing
# Indexování a slicing jsou operace které vám umožňují udělat podvýběr z nějaké kolekce. Python indexuje od `0`. Je možné používat i negativní index. Poslední element v kolekci má index `-1`. Následují příklady na textu:

text = "Hello world!"
text

text[:]

text[0:-1]

text[3:5]

text[2:-2]

len(text)

# Pozor, né každý objekt má index! Viz následující příklad.

# !!!
a = 1554254
a[1]

a = str(a)
int(a[1])

# ### dir() - jak zjistit všechny vlastnosti objektu
# Pomocí funkce `dir()` můžete najít všechny vlastnosti/parametry/funkce připojené k libovolnému objektu. Pomocí této funkce tedy můžete zjistit, jestli má objekt definované operace jako sčítání, odčítání atp.. Následují příklady (výstup není tisknut, protože je dlouhý):

a_dir = dir(a)
root_dir = dir()

# ## Kontejnery
# Kontejnery jsou datové typy, které slouží ke skladování jiných (nebo stejných) datových typů.

# ### List
# List je nejvíc běžný kontejner. Je vymezen pomocí hranatých závorek `[]`. Je možný ho měnit přístupem přes index.

a = []
type(a)

b = ["1", 3.0, "a", 4]
b

b[2]

b[2] = 3
b

b[2:3] = ["a", "b", "c"]
b

c = ["1", "b"] + [3] * 3
c

b[1] = c
d = [c, b]
d

len(d)

# Zajímavost, převod textu na list:

a = list("Hello World!")
a

a = "Hello World!".split(" ")
a

# ### Tuple
# Tuple je něco jako list. Rozdíl je, že tuple nelze měnit přístupem přes index. Je vymezen pomocí kulatých závorek.

a = (1, 2, 3, "a")
type(a)

# !!!
a[1] = 1

b = a + (1, 2) * 2
b

c = (a, b)
c

# ### Dictionary (slovník)
# Slovník je neseřazená kolekce párů (klíč, hodnota). Kolekce není řazená protože jejím indexem jsou klíče. Slovník je tedy možné chápat jako list, v kterém index nemusí být jen celá čísla, ale cokoliv (jakýkoliv hashovatelný objekt). Slovník je vymezent pomocí složených závore `{}`. Následují příklady.

a = {}
type(a)

a = {"key1": "value1", "key2": "value2"}
a

a["key1"]

a["key1"] = 133
a

a["new_key"] = 2.0
a

# Některé užitečné funkce jsou ukázány v následujících příkladech. Kompletní seznam vlastnosti/funkcí je možné získat pomocí funkce `dir()`.

a.keys()

a.items()

a.get("key2", "Does not exist")

a.get("key100", "Does not exist")

# ### Set (množina)
# Datový typ `set` představuje množinu, podobně jako jí známe z matematiky. Tento typ není často používán. Zde je uveden spíše pro zajímavost. V běžné praxi se používá pouze jako trik, jak se zbavit duplicitních elementů v kontejneru.

a = (1, 3, 4, 5, 3, 5, 1, 8, 8, 8, 1)
a = set(a)
a = tuple(a)
a

# ## Řizení chodu programu

# ### Vyhodnocení výrazu
# Následují ukázky využítí různých operátorů pro porovnání.

1 > 2

1 <= 2

"a" == "a"

1 == 2

"1" == 1

True == 1

False == 1

3 > 2 > 1

(1 > 2) or (3 == 3)

(1 > 2) and (3 < 4)

# Negace může být realizována pomocí `not` před výrazem, nebo pomocí operátoru `!=`.

1 != 1

not 1 == 1

# Pozor, `list` a `str` jsou `True`, pokud nejsou prázdné.

True == []

True == [1, 2]

True == "abc"

True == ""

(not True == "") == (len("") == 0)

# ### Podmínka IF
# Příklady podmínky IF (a ELSE, ELIF) následují:

if True:
    print("It is True")

a = 0
if not a == 0:
    print("It is True")
else:
    print("It is not True")

a = 0
if a:
    print("It is True")
else:
    print("It is not True")

a = 2
if a == 1:
    print("a is 1")
elif a == 2:
    print("a is 2")
else:
    print("a is different from 1 and 2")

# Něco navíc: Python obsahuje i takzvaný *ternary operator*:

a = 1
b = "abc" if a == 1 else "def"
b

# ### Smyčka FOR
# Smyčka FOR slouží k iterování přes iterovatelný objekt.

a = "Hello"
for letter in a:
    print(letter)  

a = ["1", "a", [1, 2]]
for item in a:
    print(item)

# Pokud potřebujete for smyčku použít jako počítadlo, můžete iterovat přes řadu čísel získanou pomocí funkce `range`.

for idx in range(1, 4):
    print(idx)

a = [1, 4, 5, 8]
for idx in range(0, len(a)):
    print(idx, a[idx])

a = {"key1": "value1", "key2": "value2"}
for key, value in a.items():
    print(key, value)

# Něco navíc: v pythonu existuje *list comprehension* a generátory. Výstupem *list comprehension* je list. Výstupem generátoru je iterovatelný objekt.

# list comprehension
a = ["Hello " + name for name in ["John", "Alice", "Bob"]]
a

# generator
a = ("Hello " + name for name in ["John", "Alice", "Bob"])
print(a)
for item in a:
    print(item)

# ### Smyčka WHILE
# Smyčka while slouží k iterování do doby než je splněna podmínka. Příklady následují.

a = 0
while a < 5:
    print("Waiting...", a)
    a += 1

# ## Import
# Příkaz import slouží k importu dalších funkcí (tříd, objektů, ...) z externích souborů. Importovat je možné balíčky obsažené v instalaci Pythonu, balíčky instalované z exterích zdrojů, nebo vlastní lokálně skladované balíčky. V tuto chvíli budeme importovat pouze balíčky ze základní instalace Pythonu. Následují příklady:

import time
time.time()

from time import time
time()

from time import time as t
t()

# Poznámka: ověřit úspěšnost importu je možné opět pomocí funkce dir(). Stejně tak je možné pomocí funkce dir obsah balíčku.

# ## Přístup k souborům

# +
f = open("data/example.txt", "w")
f.write("Hello!")
f.close()

f = open("data/example.txt", "r")
content = f.read()
f.close()

print(content)

# +
with open("data/example.txt", "w") as f:
    f.write("Hello again!")

with open("data/example.txt", "r") as f:
    content = f.read()

print(content)
# -

# ## K zapamatování

# ### Funkce používají kulaté závory, do kterých se píšou argumenty. Následují různé správné použití:

print()
print(1)
print(1, end=" ")
list()
list([1, 3, 3])

# ### Index používá hranaté závorky. Následují příklady:

[1, 2, 3, 4][:3]
(1, 3, 3)[-1]
"abadsfqwe"[2:4]

# ### K adresování vlastnosti nebo funkce nějakého objektu, se používá tečka (objekt.funkce). Následující příklady:

(1, 3, 5, 4, 1, 2, 4).count(1)

"fa sdf ad".split(" ")

"_".join(["a", "b", "c"])

StarcoderdataJupyterScriptsDedupFiltered