previous up next how to end end

1. Jak se tvoří program

  1. Formální a přirozené jazyky
  2. Co je program?
  3. Programovací jazyk Python
  4. Co je ladění?
    1. Formální chyby
    2. Chyby při běhu programu
    3. Významové chyby
    4. Experimentální ladění
  5. Komentáře
  6. První program
  7. Glosář
  8. Cvičení

Cílem této knihy je naučit čtenáře myslet jako erudovaný programátor. Tento způsob myšlení spojuje některé z výtečných rysů matematiky, jakož i technických a přírodních věd. Programátoři stejně jako matematici používají formálního jazyka k vyjádření svých myšlenek. Stejně jako inženýři i oni navrhují objekty sestavováním částí do celků a porovnávají výsledky jednotlivých alternativ. Stejně jako vědci i programátoři pozorují chování komplexních systémů, tvoří hypotézy a předpoklady výsledků.

Nejdůležitější dovedností programátora je schopnost řešit problém. Řešit problém vyžaduje schopnost jej formulovat, tvořivě přemýšlet o možnostech řešení a zvolené řešení potom jasně a stručně vyjádřit. Učit se programovat je vynikající příležitost pro osvojení těchto dovedností.

Budeme se tedy jednak učit programovat, což je užitečná dovednost sama o sobě, jednak budeme programování používat jako prostředek k dosažení jistého cíle. Jak budeme v učení postupovat, bude se nám tento cíl stávat zřejmější.


1.1 Formální a přirozené jazyky

Přirozené jazyky jsou jazyky, kterými lidé hovoří - čeština, angličtina, španělština, atd. Tyto jazyky nebyly člověkem vytvořeny (i když se snaží jim vnutit jistá pravidla), vyvinuly se přirozenou cestou.

Formální jazyky jsou jazyky, které sestavil člověk pro nějaký účel. Matematika například používá svůj formální jazyk k vyjádření vztahů mezi čísly a symboly. Chemici používají svůj formální jazyk k zobrazení chemických struktur.

Programovací jazyky jsou formální jazyky, které byly vytvořeny jako výrazový prostředek pro usměrnění práce počítače.

Formální jazyky mívají přísná pravidla pro skladbu (syntaxi). Například, 3+3=6 je syntakticky správný matematický výraz, ne už 3=+6$. H2O je syntakticky správné chemické označení, na rozdíl od 2Zz.

Pravidla skladby jsou dvojího druhu. Ty, které určují použitelné znaky (tokens) a ty, které určují jejich vzájemné propojení (strukturu). Znaky jsou základní prvky jazyka, jako jsou slova, čísla a chemické prvky. Jedním z problémů zápisu 3=+6$ je to, že $ není legálním znakem v matematice. Podobně zápis 2Zz není legální proto, že neexistuje chemický prvek se zkratkou Zz.

Druhý typ chybné skladby souvisí se strukturou výrazů, to je se způsobem, jakým jsou znaky uspořádány. Výraz 3=+6$ je skladebně nesprávný, protože nelze umístit znak plus bezprostředně za rovnítko. Rovněž tak označení molekul musí mít index za jménem, nikoliv před ním.

Čteme-li větu v angličtině či češtině nebo výraz formálního jazyka, musíme rozpoznat, jaká je jejich skladba. Tomuto procesu, který u přirozeného jazyka provádíme podvědomě, říkáme parsing, neboli analýza skladby.

Slyšíme-li například větu "Svíce mu dohořela", rozumíme, že "svíce" je podmět a "dohořela" je přísudek. Jakmile takto rozebereme větu, můžeme usoudit co vyjadřuje, neboli určit její sémantiku. Za předpokladu ovšem, že víme co znamená slovo svíce a co slovo dohořela.

I když formální a přirozené jazyky mají mnho společných rysů - znaky, strukturu, syntaxi a sémantiku - mají také mnoho rozdílů:

mnohoznačnost
Přirozené jazyky jsou plny mnohoznačností, s nimiž se lidé vyrovnávají pomocí větných souvislostí a jiných doplňkových informací. Formální jazyky jsou navrhovány tak, aby byly téměř úplně jednoznačné, to znamená, že každý výraz má pouze jeden význam bez ohledu na souvislosti.
nadbytečnost
Mnohoznačnost a z toho plynoucí možnost nedorozumění se u přirozených jazyků vyvažuje nadbytečností výrazů. Formální jazyky jsou méně nadbytečné (redundantní) a více stručné (concise).
doslovnost
Přirozené jazyky jsou plné idiomů a metafor. Řeknu-li "Svíce mu dohořela", mluvím jako poeta a nechci tím zajisté říci, že má teď o jednu hořící svíčku méně, nýbrž že skonal. Formální jazyky míní přesně to, co říkají.

Protože přirozený jazyk používáme od nejútlejšího dětství, můžeme mít problémy s používáním formálního jazyka. Někdy lze rozdíl mezi formálním a přirozeným jazykem přirovnat v menší míře k rozdílu mezi prózou a poezií.

poezie
Slova jsou užita pro jejich znění stejně jako pro jejich význam a celá báseň vyvolává emociální odezvu. Mnohoznačnost je nejenom častá, ale i často záměrná.
próza
Doslovný význam slov je zde více důležitý a větná skladba přispívá k významu vět. Próza je použitelnější pro analýzu než poezie, přesto je stále ještě příliš mnohoznačná.
programy
Význam počítačového programu je jednoznačný a doslovný a může být určen pouhou analýzou jeho znaků a struktury.

Zde je několik rad pro čtení programů (a jiných formálních jazyků). Za prvé, mějme na paměti, že text formálního jazyka je významově zhuštěnější než text přirozeného jazyka a proto jeho čtení zabere více času. Také jeho struktura je velice důležitá, takže nebývá dobrým nápadem číst pouze zhora dolů, zleva doprava. Místo toho si zvykejme provádět v mysli rozbor skladby (parsing), rozeznávaje znaky a hodnotíce strukturu. Nakonec nezapomínejme, že záleží na maličkostech. Nepřesnost, která nám projde v přirozeném jazyce, má ve formálním jazyce dalekosáhlý význam.


1.2 Co je program?

Program je posloupnost instrukcí, které určují jak má být výpočet proveden. Výpočtem může být řešení matematické úlohy, jako je např. řešení systému rovnic či určení kořenů polynomu nebo jím může být symbolický výpočet, jako je vyhledání a výměna textu v dokumentu nebo (kupodivu) kompilování programu.

Podrobnosti se v různých jazycích liší, ale některé základní instrukce se vyskytují téměř v každém jazyce:

vstup (input)
Vložit údaje (data) z klávesnice, souboru či jiného zařízení.

výstup (output)
Zobrazit údaje (data) na obrazovce nebo je poslat do souboru či jiného zařízení.

matematika (math)
Provést základní matematické operace jako je například sčítání a odčítání

podmíněné provedení (conditional execution)
Ověřit jisté podmínky a provést příslušnou posloupnost příkazů.

opakování (repetition)
Provést něco opakovaně, obvykle s jistou obměnou.

Věřte či nevěřte, to je téměř všechno z programování. Každý program, který kdy použijete, jakkoliv komplikovaný, se bude skládat z instrukcí více či méně podobných výše uvedeným. Programování můžeme vlastně prezentovat jako proces rozdělování komplexní úlohy do menších a menších podúloh, až tyto podúlohy jsou tak jednoduché, že se dají provést pomocí těchto zákládních instrukcí.


1.3 Programovací jazyk Python

Python je příkladem jazyka vyšší úrovně, stejně jako C++, PHP a Java.

Z označení "jazyk vyšší úrovně" lze usoudit, že také existují jazyky nižší úrovně. Je tomu skutečně tak, tyto jazyky se nazývají "strojové jazyky" nebo "jazyky esembleru". Přibližně lze říci, že počítače umějí realizovat pouze programy, psané v jazycích nižší úrovně. Proto musejí být programy psané v jazyce vyšší úrovně upraveny před tím než mohou být spuštěny, což je jejich určítá nevýhoda, neboť tato dodatečná úprava zabere jistý čas.

Výhody jsou zato obrovské. Za prvé, programovat v jazyce vyšší úrovně je mnohem snadnější. Programy psané v jazyce vyšší úrovně zaberou méně času k zapsání, jsou kratší a snadněji se čtou. Je větší pravděpodobnost, že se v nich nedopustíme chyb. Za druhé, jazyky vyšší úrovně jsou přenosné, což znamená, že mohou běžet na různých druzích počítačů s několika málo nebo žádnými úpravami. Jazyky nižší úrovně lze spustit pouze na jednom druhu počítače a pro jiný musí být přepsány.

Vzhledem k těmto výhodám jsou téměř všechny programy psány v jazycích vyšší úrovně. Jazyky nižší úrovně se používají jen pro několik málo specializovaných aplikací.

Dva druhy programů přetvářejí jazyky vyšší úrovně na jazyky nižší úrovně: překladače a kompilátory. Překladač (interpreter) čte program psaný v jazyce vyšší úrovně a provádí jej, to jest dělá to, co mu program říká. Zpracovává program postupně po krátkých úsecích, střídavě je čtouce a realizujíce.

pic

Kompilátor (compiler) přečte a přeloží program najednou před tím než jej spustí. V tomto případě se program v jazyce vyšší úrovně nazývá zdrojový kód (source code) a přeložený program je cílový kód (object code), nebo strojový kód (executable). Jakmile je program jednou zkompilován, lze jej opakovaně spouštět bez opětovného překládání.

pic

Mnohé moderní jazyky používají oba procesy. Nejprve jsou zkompilovány na jazyk nižší úrovně zvaný binární kód (byte code), který je potom interpretován programem, jemuž říkáme virtuální stroj (virtual machine).

Stejný postup používá Python. Text pogramu, případně programového příkazu (zdrojový kód) je nejprve překladačem kompilován na objektový kód, kteý je posléze programovou smyčkou, zvanou PVM (Python Virtual Machine), zpracován pro výstup.

Programový balík Pythonu se běžně skládá ze tří částí:

Existují dva způsoby použití překladače Pythonu - interaktivní režim (shell mode) a programový režim (program mode). V interaktivním režimu píšeme text kódu do okna interaktivní konzoly (shell); překladač tento text přečte, vyhodnotí a vrátí (vytiskne) výsledek. V dalším textu budiž tato konzola označována zkratkou IPP (interaktivní prostředí Pythonu):

Python 3.3.0 (default, Sep 29 2012, 10:55:48)
[MSC v.1600 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license"
 for more information.
>>> 2+3
5

Skupina znaků >>> se nazývá prompt (výzva) a překladač jím naznačuje, že je připraven přijímat instrukce. Zapsali jsme print(2+3), překladač náš výraz vyhodnotil a na dalším řádku odpověděl 5.

Práce v IPP je vhodná pro testování krátkých kódů. Činnost překladače ukončíme příkazy exit(), Ctrl+z, případně Ctrl+d v Linuxu.

Alternativně můžeme napsat program do souboru a použít překladače k provedení jeho obsahu. Takovému souboru říkáme skript. S použitím textového editoru vytvoříme soubor s názvem firstprogram.py v němž zapíšeme příkaz:

# -*- coding:utf-8 -*-

print(2+3) 

Dle zavedené konvence dáváme souborům s programem v Pythonu příponu  .py . Podle této přípony pozná překladač, že se jedná o soubor, obsahující kód Pythonu.

> python firstProgram.py
5

Kompilované soubory překladač ukládá do souborů s příponou .pyc.

Pro spouštění skriptů můžeme kromě IPP s výhodnou použít program IDLE nebo PyScripter. PyScripter je nejlepší ze všech světů.

pic

V zobrazené ukázce vidíme otevřené okno programu IDLE (Python Shell), kde jsem příkazem File > New otevřel okno senzitivního editoru, do něhož jsem zapsal text programu, uložil a příkazem  Run > Run Module spustil jeho provedení - v konzole se vynořil výsledek 5.

Skript Pythonu se normálně skládá pouze ze znaků sady ASCII (0-127). Použijeme-li na prvním nebo druhém řádku kódovací direktivu s kódováním např. # -*- coding:utf-8 -*-, můžeme toto kódování použít v komentářích a v řetězcích.


1.4 Co je ladění?

Programování je složitý proces a protože jej provádí lidská bytost, je často provázeno chybami. Chyba v programu je z potměšilých důvodů označována jako bug (štěnice, veš) a proces vyhledávání chyb a jejich oprava se v originále logicky nazývá debugging (odvšivení), my používáme ladění.

V programu se mohou vyskytnout tři druhy chyb: chyby související se skladbou programu (syntax errors), s během programu (runtime errors) a s významem programu (semantic errors). Je užitečné mezi nimi rozlišovat kvůli jejich rychlejšímu vyhledání.

1.4.1 Formální chyby

Python může provést výpočet jenom pro takový program, který má správnou skladbu (syntaxi). Nemá-li, je běh programu ukončen a překladač vrací chybové hlášení. Slovo syntaxe se vztahuje ke skladbě programu a k pravidlům skladby. V češtině i angličtině musí například věta začínat velkým písmenem a končit tečkou.

tato věta je chybná z hlediska syntaxe. Rovněž i tato

Pro většinu čtenářů nepředstavuje několik málo chyb v syntaxi výrazný problém, pročež můžeme číst některou moderní poezii aniž by naše vědomí produkovalo "chybová hlášení". Python takto snášenlivý není. Jakmile se kdekoliv v programu objeví syntaktická chyba, překladač vytiskne chybové hlášení, ukončí běh programu a nelze s ním hnout. V prvních týdnech naší programátorské kariéry strávíme pravděpodobně hodně času vyhledáváním takovýchto chyb. Po nabytí jisté zkušenosti jich však už budeme dělat méně a rychleji je nalezneme.

1.4.2 Chyby při běhu programu

Druhým typem chyb je chyba při běhu programu. Takováto chyba se neobjeví dříve, než program spustíme. Tyto chyby se také nazývají výjimky (exceptions), protože obvykle ukazují na to, že se stalo něco mimořádného (a špatného).

V jednoduchých programech počátečních kapitol se exekuční chyby vyskytnou vzácně, takže se s nimi setkáme patrně až v pozdějších kapitolách.

1.4.3 Významové chyby

Třetím typem chyb jsou chyby významové (sémantické). Objeví-li se v programu sémantická chyba, proběhne program úspěšně v tom smyslu, že se neobjeví žádné chybové hlášení, ale program neprovede to, co jsme zamýšleli. Provede něco jiného. Přísně vzato, provede to, co jsme mu řekli, aby provedl.

Problém spočívá v tom, že program, který jsme napsali, není ten program, který jsme chtěli napsat. Vyznění programu (jeho sémantika) je špatné. Nalezení sémantických chyb může být někdy náročné, protože to vyžaduje zpětné porovnávání výstupu s tím, co jej v programu způsobuje.

1.4.4 Experimentální ladění

Vyhledávání chyb je nejdůležitější dovednost, kterou potřebujeme získat. I když to může být frustrující, vyhledávání chyb je intelektuálně nejbohatší, nejnáročnější a nejzajímavější část programování.

Svým způsobem připomíná hledání chyb práci detektiva. Jsme konfrontováni s indiciemi z nichž máme určit procesy a události, které vedly k výsledkům, jež máme před sebou.

Vyhledávání chyb je něco jako experimentální věda. Jakmile nás napadne, v čem může chyba spočívat, upravíme program a vyzkoušíme jej. Byla-li naše hypotéza správná, můžeme získanou zkušenost zobecnit a použít příště. Nebyla-li naše hypotéza správná, musíme si vymyslet jinou. Jak jednou poznamenal Sherlock Holmes: "Poté, co jsme vyloučili nemožné, vše co zůstává, ať jakkoliv nepravděpodobné, musí být pravdivé". (A. Conan Doyle, Podpis čtyř)

Pro někoho splývá vyhledávání chyb s programováním. To jest programování jako postupné odstraňování chyb z programu, až posléze program dělá to, co si přejeme. Jinými slovy, začneme s programem, který "něco" správně dělá a postupně jej malými úpravami a debugováním přeměníme na fungující program, který dělá to, co si přejeme.

Linux například je operační systém, který obsahuje tisíce řádek kódu, ale původně to byl jednoduchý program, který Linus Torvalds sestavil ke zkoumání čipu Intel 80386 (The Linux User´s Guide, Beta Version).

V pozdějších kapitolách uvedeme více pokynů k ladění a k dalším programátorským technikám.


1.5 Komentáře

Tím jak se program stává větším a složitějším, stává se také méně přehledným. Formální jazyky jsou hutné a často je obtížné při pohledu na část kódu určit, co má být prováděno a proč.

Proto je dobré doplnit program poznámkami, které vysvětlují, co příslušná část programu má provádět. Poznámky či komentáře uvádíme symbolem #.

# compute the percentage of the hour that has elapsed 
percentage = (minute * 100) // 60 

Poznámka je v tomto případě umístěna na samostatné řádce. Lze ji umístit také na konec řádky:

percentage = (minute * 100) // 60 # celočíselné dělení 

Všechno od znaku # (hash) až do konce řádku je ignorováno - nemá na program žádný vliv. Informace je určena pro programátora nebo budocí programátory, kteří mohou programový kód používat. V tomto případě je čtenář upozorněn na vždy překvapující chování celočíselného dělení.


1.6 První program

První program jsme si vlastně již napsali na konci odstavce 1.3. Byl to skutečný program, protože jsme jej zapsali do skriptu a jiným programem jsme jej spustili.

Protože ale bývá obvyklé začínat pozdravem "Hello World!", uvedeme si tuto ukázku alespoň dodatečně. V tomto případě se jak zápis kódu, tak jeho vyhodnocení a výstup uskuteční v IPP.

Současně s "prvním programem" se seznámíme s první funkcí, kterou budeme používat.

V Pythonu 2.x bychom použili příkaz:

>>> print "Hello, World!"
Hello, World! 

Uvozovky označují začátek a konec hodnoty, ve výsledku se neobjeví.

V Pythonu 3.x je print funkcí, a proto musíme použít závorky:

>>> print ("Hello, World!")
Hello, World! 


1.7 Glosář

algoritmus (algorithm)
Obecný proces řešení jisté kategorie problémů.
bug
Chyba v programu.
bajtový kód (byte code)
Prostředník mezi zdrojovým kódem a objektovým kódem. Mnohé moderní jazyky nejprve kompilují zdrojový kód do bajtového kódu a ten potom překládají programem zvaným virtuální stroj
kompilovat (compile)
Přeložit program z jazyka vyšší úrovně do jazyka nižší úrovně najednou jako přípravu na jeho pozdější provedení.
odladění (debugging)
Proces nalezení a odstranění chyby z programu.
výjimka (exception)
Jiné jméno pro chybu při běhu programu.
strojový kód (executable)
Jiné jméno pro cílový kód, který je připraven k provádění.
formální jazyk (formal language)
Jakýkoliv jazyk, který lidé vytvořili s určitým záměrem, jako je prezentace matematických vztahů nebo počítačových programů.
jazyk vyšší úrovně (high-level language)
Programovací jazyk jako je Python, který byl navržen tak, aby jej uživatel mohl snadno zapisovat a číst.
překládat (interpret)
Provádět program v jazyce vyšší úrovně jeho postupným překládáním řádek po řádku.
jazyk nižší úrovně (low-level language)
Programovací jazyk, který je navržen tak, aby jej počítač mohl snadno zpracovat; také nazýván strojový jazyk nebo jazyk asembleru.
přirozený jazyk (natural language)
Jakýkoliv jazyk, jímž lidé hovoří a jenž vznikl přirozenou cestou.
cílový kód (object code)
Program, přeložený kompilerem.
analýza skladby (parsing)
Zkoumání programu a analýza jeho skladebného uspořádání.
přenositelnost (portability)
Vlastnost programu běžet na více než jednom druhu počítače.
příkaz k tisku (print())
Funkce, která způsobí že překladač Pythonu zobrazí zadanou hodnotu na výstupním zařízení.
řešení problému (problem solving)
Proces formulování problému, nalezení řešení a vyjádření tohoto řešení.
program (program)
Řada instrukcí, které určují postup výpočtu.
interaktivní rozhranní Pythonu (Python shell)
Interaktivní uživatelské rozhraní (IPP) překladače Pythonu. Uživatel zapisuje příkazy za výzvu (>>>) a klávesnicí Enter je posílá překladači ke zpracování.
chyba při běhu programu (runtime error)
Chyba, která se objeví až při spuštění programu a která brání v jeho pokračování.
skript (script)
Program uložený v souboru (zpravidla ten, který bude překládán).
sémantika (semantics)
Význam či smysl programu.
sémantická chyba (semantic error)
Chyba v programu, která způsobí, že program dělá (bezchybně) něco jiného, než co bylo zamýšleno.
zdrojový kód (source code)
Program v jazyce vyšší úrovně před kompilací.
syntaxe (syntax)
Struktura, neboli skladba programu.
chyba skladby (syntax error)
Chyba v programu, která znemožňuje rozbor skladby (parsing) a tudíž brání jeho překladu.
znak (token)
Jeden ze základních prvků skladebného uspořádání programu, podobně jako slovo v přirozeném jazyce.

1.8 Cvičení

  1. Napište českou větu s pochopitelným významem ale nesprávnou skladbou. Potom napište další větu se správnou skladbou ale s nesprávnou sémantikou.
  2. Spusťte překladač Pythonu. Zapište 1+2 a stiskněte Enter. Python vyhodnotí tento výraz, vypíše výsledek a vypíše výzvu >>> (prompt) .
    Znak * je operátor násobení a ** je operátor pro umocňování. Experimentujte s těmito operátory a pozorujte, jaké výsledky jsou Pythonem zobrazovány. Co se stane, když použijete operátor // ? Jsou výsledky dle vašeho očekávání?
  3. Zapište 1 2 a stiskněte Enter. Python se pokouší vyhodnotit výraz ale nemůže, protože není skladebně správný. Namísto toho dává chybové hlášení:
      File "<stdin>", line 1
        1 2
          ^
    SyntaxError: invalid syntax
    
    V mnoha případech Python ukáže místo, kde k chybě došlo, ale toto označení není vždycky správné. Také příčina chyby není vždy podrobně uvedena. Takže nám nezbývá, než se řádně naučit pravidla skladby. V našem příkladě si Python stěžuje, protože mezi čísly není žádný operátor.
  4. Zapište print('hello'). Python provede tento příkaz tak, že vypíše hello. Všimněte si, že uvozovky, které jsme použili k vymezení řetězce, nejsou součástí výstupu. Nyní zapište print ('"hello"') a zkoumejte výsledek.
  5. Zapište print(tvaroh) bez uvozovek. Odezva bude vypadat nějak takto:
    Traceback (most recent call last):
      File "<stdin>", line 1, in ?
    NameError: name 'tvaroh' is not defined
    
    Toto je chyba při běhu programu, podrobněji NameError (chyba jména) a ještě více podrobněji to je chyba proto, že jméno tvaroh není definováno. Nevíte-li, co to znamená, nevadí, brzy na to přijde řeč.
  6. Zapište 'Toto je test ...' za prompt Pythonu a stiskněte Enter. Sledujte co se provede. Nyní vytvořte skript s názvem test1.py se stejným obsahem (nezapomeňte jej uložit, než jej spustíte):
    'Toto je test ...'
    
    Co se stane, když ten skript spustíte? ... Nyní změňte obsah takto:
    print('Toto je test ...')
    
    uložte a spusťte jej znova. Co se stalo tentokrát?

    Kdykoliv zapíšeme výraz za výzvu Pythonu, je vyhodnocen a výsledek se zapíše o řádek níže. 'Toto je test ...' je výraz, který se vyhodnotí a vypíše jako 'Toto je test ...' (stejně jako výraz 42 se vyhodnotí a vypíše jako 42). Vyhodnocený výraz ze skriptu však není posílán na výstup a je tedy zapotřebí jej explicitně volat příkazem print().

previous up next how to end end