DoDo / Programování

Mirek Kučera - vvendigo@seznam.cz

23. září

Instalace jazyka Python pro Windows

Stačí v Microsoft Store zahledat Python a nechat nainstalovat verzi 3.10 (ale pro naše účely lze použít i jakoukoli jinou verzi > 3.1).

Druhou možností, např. pro jiný operační systém, je stáhnout a nainstalovat balík z python.org.

V nabídce programů přibude Python a IDLE.

IDLE

Po spuštění se objeví tzv. konzole, do které můžeme psát matematické výrazy i jakékoli příkazy jazyka Python. Po stisknutí klávesy Enter se daný příkaz vyhodnotí.

Například:

>>> 1 + 1
2
>>> max(1, 3, 2)
3
>>> "+" * 20
'++++++++++++++++++++'

První program

V menu IDLE vlevo nahoře, zvolíme File -> New File a otevře se okno editoru. První program bude opravdu jednoduchý:


print("Ahoj, Světe!")

Program spustíme pomocí menu editoru Run -> Run module. Před spuštěním musíme program uložit, spouští se ze souboru z disku.

Spuštění lze urychlit použitím klávesových zkratek: Ctrl+S (uložit) a pak F5 (spustit modul).

30. září

Funkce print()

Tato funkce tiskne na obrazovku parametry, které jí dáme. Parametry píšeme do závorek za jméno funkce. Vyzkoušet to lze v konzoli. Např.

>>> print("Ahoj!")
Ahoj!
>>> print("Cislo jedna:", 1)
Cislo jedna: 1

Po vytištění parametrů funkce ukončí ("skočí na nový") řádek. Pokud nezadáme parametr žádný, vytiskne jen prázdný řádek. To jsem použil v programu ukazujícím odlet rakety:

print("  I  ")
print(" XXX ")
print(" XOX ")
print(" XXX ")
print("XXXXX")
print("XXXXX")
print("XX XX")

print()
print()
print()
print()
print()
print()
print()
print()
print()
print()
print()
print()
print()
print()
print()

Zmínil jsem pojem ASCII art - kreslení pomocí znaků.

for cyklus

Opakované psaní stejné funkce je dost otravné. Proto počítačové jazyky obsahují konstrukci cyklu. V případe Pythonu je trochu specifická: for JMENO_PROMENNE in POSLOUPNOST_DAT:. Následující řádky, odsazené o stejný počet mezer jsou pak vykonány tolikrát, kolik je prvků v POSLOUPNOST_DAT (této skupině řádků se říká tělo cyklu). Pro naší raketu jsem to použil takto:

print("  I  ")
print(" XXX ")
print(" XOX ")
print(" XXX ")
print("XXXXX")
print("XXXXX")
print("XX XX")

for X in range(0, 40):
    print()

Funkce range(OD, DO, KROK) vyrobí potřebnou posloupnost dat - čísel od OD do čísla DO-1. Abychom viděli čísla co vyrobí v konzoli, musíme ji předat jako parametr do funkce list(), která z nich vyrobí seznam:

>>> range(0, 10)
range(0, 10)
>>> list( range(0, 10) )
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list( range(0, 10, 2) )
[0, 2, 4, 6, 8]
>>> list( range(10, 0, -1) )
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

V našem případě nás ta čísla ale nezajímají, jde nám jen o ten počet opakování cyklu. Kdybychom ale chtěli, můžeme v těle cyklu pracovat s proměnnou X (do které Python postupně dává čísla z posloupnosti), jak jsem ukazoval na "odpočtu před startem".

Proměnná

Použil jsem termín proměnná. Zjednodušeně lze říct, že je to pojmenování místa v paměti počítače, kam si ukládáme nějakou hodnotu. Např. číslo nebo text ("řetězec").

Proměnnou vyrobíme přiřazením - napíšeme nějaké jméno (může obsahovat velká a malá bez diakritiky, číslice a "podtržítka" [znak _]), znak = a hodnotu. Následně můžeme používat název proměnné tam, kde bychom jinak použili hodnotu:

>>> vyska_stromu = 12
>>> print("Strom měří", vyska_stromu, "metrů.")
Strom měří 12 metrů.
>>> jmeno = "Karel"
>>> print("Jmenuje se", jmeno, "a stoji u stromu mericiho", vyska_stromu, "metru.")
Jmenuje se Karel a stoji u stromu mericiho 12 metru.

Proměnné se hodí tam, kde chceme nějakou hodnotu použít opakovaně. Zároveň pak máme možnost ji měnit změnou na jednom místě programu.

Knihovny (moduly)

Python sám nabízí jen nejnutnější funkce. Pokud potřebujeme něco víc, musíme si do programu přidat knihovnu, která danou funkci obsahuje. Už základní instalace Pythonu ale obsahuje spoustu šikovných knihoven.

Nám by se hodilo odlet rakety trochu zpomalit. Na to lze použít funkci sleep() z knihovny time. Knihovnu načteme příkazem import:

import time

print("  I  ")
print(" XXX ")
print(" XOX ")
print(" XXX ")
print("XXXXX")
print("XXXXX")
print("XX XX")

for _ in range(0, 10):
    print(" ...")
    time.sleep(0.2)

for _ in range(0, 30):
    print("")
    time.sleep(0.1)

Přerušení programu

Program lze přerušit stisknutím kláves Ctrl + C.

Nápověda

Python nabízí nápovědu. Jednak při psaní v editoru, ale i v konzoli, kde se vyvolá příkazem help():

>>> help(print)
print(...)
    print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
    
    Prints the values to a stream, or to sys.stdout by default.
    Optional keyword arguments:
    file:  a file-like object (stream); defaults to the current sys.stdout.
    sep:   string inserted between values, default a space.
    end:   string appended after the last value, default a newline.
    flush: whether to forcibly flush the stream.

O printu se tu dozvíme například to, že můžeme změnit znaky oddelující vytištěné hodnoty (sep) i znak, který se vytiskne na konci řádku (end - '\n' je speciální znak, který ukončuje řádek). Jsou to takzvané "pojmenované parametry", protože jim může předcházet libovolné množství hodnot, které chceme prostě vytisknout. Vidíme i hodnoty, které se použijí, pokud nastavení nezměníme (defaults).

Můžeme tak vyrobit např. jednoduchý program, který vytiskne posloupnost čísel na jeden řádek:

for cislo in range(0, 10):
    print(cislo, end="")

Pokud zkusíte help(range), zjistíte, že to vlastně žádná funkce není. Je to něco daleko složitějšího, ale to zatím nebudeme rozebírat. :)

7. října

Komentáře

Do programu si můžeme psát poznámky, takzvané "komentáře". Jde to dvěma způsoby:

# <- pouzitim "hashtagu" - zbytek radku za timto znakem pocitac ignoruje

# lze ho napsat na samostatny radek

print("ahoj!") # ale i na konec radku, ktery neco vykonava

print("ale hashtag # uvnitr retezce jako komentar nefunguje")

# print(a + b) # komentar lze pouzit i na docasne "vypnuti" casti programu

# druhou moznosti je pouziti viceradkoveho retezce (misto jednech uvozovek se uzavira do trech):
"""
toto je
viceradkovy
komentar

tento kod se nevykona:
print("huhu")
"""

Funkce input()

Funkce input() dává uživateli možnost zadat nějakou vstupní hodnotu. Jako parametr se jí dává text výzvy:

a = input("Zadejte cislo: ")
a = int(a)

b = input("Zadejte druhe cislo: ")
b = int(b)

print("Souctem", a, "a", b, "je", a + b)

Typy proměnných

Narazili jsme na to, že Python rozlišuje typ proměnné nebo hodnoty. Například je rozdíl mezi číslem a řetězcem, protože některé operace nemusí pro různé typy hodnot dávat smysl. Třeba dělení řetězce číslem nebo jiným řetězcem:

>>> "karel" / 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: unsupported operand type(s) for /: 'str' and 'int'

# Ani retezec obsahujici cislo nebude fungovat.
# Python obsah retezce nezkouma, je to pro nej proste spatny typ hodnoty pro deleni:

>>> "6"/2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: unsupported operand type(s) for /: 'str' and 'int'

Vlastní modul/knihovna

Udělat si vlastní modul v Pythonu není nic těžkého. Je to prostě soubor s definicemi funkcí a případně proměnných apod.

Důležité je, aby byl buďto ve stejném adresáři jako program, kde ho chcete použít, nebo v adresáři, který ma Python nastaven pro hledání knihoven. Přednostně se hledá v adresáři s programem.

# soubor mujmodul.py

def ahoj(jmeno):
    print("Ahoj", jmeno, "!")
# program
import mujmodul

mujmodul.ahoj("mami")

Druhá možnost importu (pouze určité funkce apod.):

from mujmodul import ahoj

ahoj("mami")

Pár odkazů

Slíbil jsem nějaké odkazy. Tu jsou:

14. října

Podmínka IF

Často potřebujeme vykonat některé příkazy jen za určitých podmínek. Na to slouží konstrukce if LOGICKY_VYRAZ: následovaný blokem příkazů, které jsou vykonány, pokud platí LOGICKY_VYRAZ (má výslednou hodnotu True). Případně můžeme ještě doplnit blok else:, který se vykoná v opačném případě.

# priklady vyrazu

>>> 1 > 2
False

>>> 10 == 10
True

# to stejne s promennymi:
>>> a = 5
>>> b = 3
>>> 
>>> a > b
True
>>> a == b
False
>>> a < b
False

Příklad programu:

cislo = input("Zadejte cislo mensi nez 10: ")
cislo = int(cislo)

if cislo < 10:
    print("Velmi spravne!")
    print("Cislo", cislo, "je mensi nez 10.")
else:
    print("Ale, ale!")
    print("Cislo", cislo, "neni mensi nez 10.")

if cislo > 15:
    print("Je vetsi, a to o hodne!")

Náhodná čísla

Další šikovnou knihovnou/modulem je random. Pro nás bude nejužitečnějčí funkce randint(MIN, MAX). Vrací náhodné celé číslo mezi MIN do MAX, včetně krajních hodnot.

>>> from random import randint
>>> randint(1, 3)
2
>>> randint(1, 3)
1
>>> randint(1, 3)
3
>>> randint(1, 3)
3
>>> randint(1, 3)
1

21. října

Velmi stručný tahák pro Python

Online na Google Docs.

Hra na hádání čísla

from random import randint

print("Myslim si cislo od 1 do 10.")
print("Hadej, ktere to je!")

cislo = randint(1, 10)
tipovane_cislo = None

while tipovane_cislo != cislo:
    vstup = input("Zadej svuj tip (1-10): ")
    tipovane_cislo = int(vstup)
    if tipovane_cislo < cislo:
        print("Me cislo je vetsi!")
    if tipovane_cislo > cislo:
        print("Me cislo je mensi!")

print("Spravne, je to", cislo, "!")

4. listopadu

Hra kámen-nůžky-papír

Kombinuje cyklus, použití seznamu (přesněji tuple) a složité podmínky.

from random import choice

moznosti = ("kamen", "nuzky", "papir")

while True:
    volba = input("Zadejte svou volbu (kamen/nuzky/papir): ")

    if volba not in moznosti:
        print(volba, "nelze pouzit!")
        continue

    volba_pocitace = choice(moznosti)
    print("Pocitac zvolil", volba_pocitace)

    if volba == volba_pocitace:
        print("Nerozhodne.")
    elif volba == "kamen":
        if volba_pocitace == "nuzky":
            print("Pocitac prohral.")
        elif volba_pocitace == "papir":
            print("Prohral jste.")
    elif volba == "nuzky":
        if volba_pocitace == "papir":
            print("Pocitac prohral.")
        elif volba_pocitace == "kamen":
            print("Prohral jste.")
    elif volba == "papir":
        if volba_pocitace == "kamen":
            print("Pocitac prohral.")
        elif volba_pocitace == "nuzky":
            print("Prohral jste.")

Vztah mezi písmeny a čísly

Každý znak (písmeno, číslice, symbol) je v počítači kódován pomocí čísla. Základní znaky odpovídají číslům 0-127 a jsou popsány ASCII tabulkou. Rozšířená verze tabulky obsahuje pak znaky až do 255.

Zjednodušeně lze říct, že dalším rozšířením tabulky vzniklo kódování Unicode, které už obsahuje miliony znaků a možnosti jejich kombinace.

Pro převod mezi čísly a znaky má Python funkce ord(ZNAK) a chr(CISLO).

>>> ord('a')
97
>>> ord(" ")
32
>>> ord('ž')
382
>>> chr(98)
'b'
>>> chr(99)
'c'

Generování náhodných slov

Za pomoci generování náhodných čísel můžeme tedy vyrábět náhodná slova.

from random import randint

delka_slova = 8

kod_a = ord('a')
kod_z = ord('z')

slovo = ''

for _ in range(0, delka_slova):
    slovo += chr(randint(kod_a, kod_z))

print(slovo)

Budou to ale podivné řetězce jako bclsmvhc nebo nvivvtht. Pokud chceme něco lepšího, je třeba počítat se slabikami.

from random import choice

slabiky = ('ba', 'la', 'ka', 'ro', 'so', 'de', 'bu', 'hu', 'si', 'li') # atd...

delka_slova = 8
slovo = ''

while len(slovo) < delka_slova:
    slovo += choice(slabiky)

print(slovo)

Ještě sofistikovanější je použití Markovových řetězců (a není to tak složité, jak by se z Wikipedie možná zdálo ;) ).

11. listopadu

Hra kámen-nůžky-papír, kde počítač podvádí

O dost jednodusší variace předchozí hry.

moznosti = ("kamen", "nuzky", "papir")

while True:
    volba = input("Zadejte svou volbu (kamen/nuzky/papir/konec): ")

    if volba == 'konec':
        break

    if volba not in moznosti:
        print(volba, "nelze pouzit!")
        continue

    volba_pocitace = "nuzky"

    if volba == "kamen":
        volba_pocitace = "papir"
    elif volba == "nuzky":
        volba_pocitace = "kamen"

    print("Pocitac zvolil", volba_pocitace, 'a vyhral!')

print("Ahoj! Tak zase nekdy priste.")

Datový typ dict(slovník)

Hodí se tam, kde chceme za běhu programu ukládát hodnoty pod různými názvy, nebo pokud prostě potřebujeme něco jako slovník.

Například převod různých možností zadání slov v naší hře:

moznosti = {
    "kamen": "kamen",
    "nuzky": "nuzky",
    "papir": "papir",
    "kámen": "kamen",
    "nůžky": "nuzky",
    "papír": "papir",
    "k": "kamen",
    "n": "nuzky",
    "p": "papir"
}

while True:
    volba = input("Zadejte svou volbu ([k]amen / [n]uzky / [p]apir / konec): ")
    # prevod na mala pismena
    volba = volba.lower()

    if volba == 'konec':
        break
    # existuje takovy klic ve slovniku?
    if volba not in moznosti:
        print(volba, "nelze pouzit!")
        continue
    # prevedeme klic na hodnotu
    volba = moznosti[volba]

    print("Zvolil jste", volba)

    # Atd...

Nebo spočítání výskytů písmen v řetězci:

text = "Ondatra udatne plovala kolem stavidla."

pocitadlo = {} # nebo dict()

for p in text: # projde text po jednotlivych pismenech
    if p in pocitadlo:
        pocitadlo[p] += 1
    else:
        pocitadlo[p] = 1

print(pocitadlo)

# pokud buchom chteli treba pocet pismen 'a':
# print("Acek je", pocitadlo["a"])

Ošetření chyb za běhu programu (výjimky)

Pokud dojde k chybě pro kterou nemá funkce nebo výraz vhodnou návratovou hodnotu, dojde k vyvolání výjimky. Zde například ValueError:

>>> int("abc")
Traceback (most recent call last):
  File "", line 1, in 
ValueError: invalid literal for int() with base 10: 'abc'

Výjimku můžeme takzvaně "odchytit" pomocí konstrukce try ... except ...:

vstup = input("Zadejte cislo: ")
try:
    cislo = int(vstup)
except:
    print("To nebylo cislo!")

Podrobněji je to popsáno třeba tady. A ještě podrobněji tady.

25. listopadu

Základní práce se soubory

Soubor musíme otevřít pomocí "funkce" open(JMENO, MOD), kde JMENO je řetězec se jménem souboru (příp. s celou cestou) a MOD je typ používání (také řetězec) - "w" zápis (založí nový, nebo otevře existující a smaže jeho obsah), "a" pokračovat v zápisu na konci souboru, "r" čtení. Lze kombinovat ještě třeba s písmenem "b" (binární přístup). Dalším mozným parametrem je kodování (pro textové soubory - když neuvedeme, použije se UTF-8). Kompletní popis je v dokumentaci


# priklady:

soubor = open("soubor.txt", "r") # budeme cist, textove

soubor = open("soubor.jpg", "rb") # budeme cist, "binarne"

soubor = open("soubor.txt", "w") # budeme zapisovat, textove

soubor = open("soubor.txt", "a") # budeme pridavat na konec, textove


soubor.read() # precte cely soubor a vrati jeho obsah jako retezec nebo binary() (podle toho jak jsme ho otevreli)

soubor.read(123) # precte a vrati 123 bytu nebo znaku ze souboru

soubor.write("moje data\n") # zapise do souboru radek textu


# pokud chceme praci se souborem ukoncit, "zavreme" ho:

soubor.close()
# zapiseme textove:
soubor = open("soubor.txt", "w")
soubor.write("Řádek textu.\n")
soubor.close()

# precteme textove:
soubor = open("soubor.txt", "r")
print(soubor.read())
soubor.close()

# Vytiskne:
#Řádek textu.
#

# precteme "binarne":
soubor = open("soubor.txt", "rb")
print(soubor.read())
soubor.close()

# Vytiskne: (je videt kodovani znaku mimo ASCII rozsah)
#b'\xc5\x98\xc3\xa1dek textu.\n'

Knihovna os

Obsahuje zajímavé funce používající operační systém.

os.getlogin() # vrati uzivatelske jmeno

os.getcwd() # vrati adresar (slozku), kde program prave pracuje (a bude tam napr. zakladat soubory, pokud jim nezadame celou cestu)

os.makedirs(CESTA) # zalozi slozku (adresar), vcetne neexistujicich nadrazenych slozek

Více v dokumentaci modulu os.

Hříčka: počet spuštění programu

Program, který si pamatuje kolikrát byl spuštěn

import os

nazev_souboru = 'pocet.txt' # aby se dal lehce zmenit, dam si ho do promenne

pocet = 0

# pokud soubor existuje, nactu z nej pocet
if os.path.exists(nazev_souboru):
    soubor = open(nazev_souboru, "r")
    pocet = int(soubor.read())
    soubor.close()

pocet = pocet + 1

print('Tento program byl spusten po ', pocet, '.', sep='')

# zapisu zvyseny pocet
soubor = open(nazev_souboru, "w")
soubor.write(str(pocet))
soubor.close()