Toto je stručný úvod do programování s příklady napsanými v jazyce Python. (Jestliže již umíte programovat, ale toužíte po úvodu do Pythonu, může se vám hodit můj článek Instant Python). Tento článek byl dosud přeložen do italštiny, polštiny, japonštiny, srbštiny, brazilské portugalštiny, nizozemštiny a češtiny.
Poznámka překladatele: Pokud v tomto textu naleznete nějakou chybu, nepřesnost, překlep,… prostě cokoliv, napište o mi tom, prosím, e-mail na adresu david(zavináč)kolibac(tečka)cz.
Tato stránka není o vlamování se do cizích počítačů apod. Nezajímá mne to, takže mi o tom, prosím, nepište.
Poznámka: Aby vše fungovalo, jak má, pište programy do textového souboru a až poté je spouštějte v interpretru; nesnažte se je psát přímo do interpretru — ne všechny pak budou fungovat. (Neptejte se mne, prosím, na detaily. Podívejte se do dokumentace nebo napište e-mail na help@python.org.)
Poznámka překladatele: Lidem neovládajícím angličtinu se může hodit česká konference o Pythonu a vůbec celý web České komunity programátorů a uživatelů jazyka Python.
Pro programování v Pythonu musíte mít nainstalovaný interpreter Pythonu. Ten existuje pro většinu platforem (včetně Macintoshe, Unixu a Windows). Více informací naleznete na webu Pythonu. Také byste měli mít textový editor (třeba Emacs, Notepad nebo něco podobného).
Poznámka překladatele: Ačkoliv je v době překladu tohoto textu již dostupný Python 3.2, který je i ze syntaktického hlediska zpětně nekompatibilní s dřívějšími verzemi, zde bude nadále používán Python verze 2.x (obvykle 2.6 nebo 2.7), jelikož se zatím nachází na většině systémů a existuje pro něj větší množství knihoven než pro novou verzi.
Když programujete počítač znamená to, že mu dáváte příkazy, co má dělat. Počítačové programy v mnoha věcech připomínají recepty, podle nichž třeba vaříme. Například [1]:
Slavnostní šunkový salát (pro 4 osoby)
Přísady:
Marináda:
1/4 šálku citronové šťávy
1/4 šálku nepříliš slané sójové omáčky
1/4 šálku vody
1 kávová lžička rostlinného oleje
3/4 kávové lžičky šalvěje
1/2 kávové lžičky oregana
1/4 kávové lžičky chilli omáčky
2 stroužky rozetřeného česneku
Salát:
1 dvanáctiuncová konzerva nepříliš slaného lančmítu (mleté kořeněné maso) nakrájeného na proužky
1 nakrájená cibule
1 na proužky nakrájená paprika
salát
12 rozpůlených keříčkových rajčat
Postup:
V nádobě s přesně sedící pokličkou smíchejte a řádně protřepejte ingredience na marinádu.
Umístěte proužky šunky do igelitového pytlíku a polijte je marinádou. Pytlík uzavřete;
marinujte jej 30 minut v ledničce. Vyjměte šunku z pytlíku; odejměte 2 kávové lžičky marinády.
Ohřejte odejmutou marinádu na velké pánvi. Přidejte šunku, cibuli a papriku. Smažte 3 až 4 minuty,
nebo dokud není šunka hotová. Vložte do 4 salátových misek listy salátu a zalijte je horkou
salátovou směsí. Ozdobte rozpůlenými rajčaty. Podávejte.
Tomuto žádný počítač rozumět nebude… A valná většina počítačů není schopna vyrobit šunkový salát i kdyby rozuměla návodu. Co tedy musíme udělat, aby to bylo pro počítač srozumitelnější? V zásadě dvě věci. Musíme (1) hovořit k počítači jazykem, kterému rozumí, a (2) musíme po něm chtít věci, které nám může splnit.
První bod znamená, že musíme použít jazyk — programovací jazyk, pro který máme interpretační program, a druhý bod znamená, že nemůžeme očekávat, že nám počítač udělá salát — ale můžeme očekávat, že bude sčítat čísla, vypisovat něco na obrazovku atd.
Je tradicí, že učebnice programovacích jazyků vždy začínají programem, který vypíše na obrazovku text „Ahoj, světe!“. V Pythonu je to velmi jednoduché:
print "Ahoj, svete!"
Poznámka překladatele: Ve zdrojových kódech příkladů v tomto textu nebude používána diakritika. Při správném nastavení systému s ní samozřejmě potíže nejsou, ale ne všechny systémy jsou správně nastavené…
Ono je to v podstatě stejné jako recept uvedený výše (ačkoliv je to mnohem, mnohem kratší). Říká to počítači, co má dělat: vypsat text „Ahoj, světe!“. Co když budeme chtít, aby toho náš program dělal více?
print "Ahoj, svete!" print "Nashledanou, svete!"
To nebylo o moc složitější, že ne? Ale také ne o moc zajímavější… Chtěli bychom udělat něco s přísadami, podobně jako v receptu na šunkový salát. Dobrá — co máme za přísady? Máme řetězce textu, jako je "Ahoj, svete!", ale máme také čísla. Dejme tomu, že chceme po počítači, aby nám spočítal obsah obdélníku. Můžeme mu tedy dát následující drobný recept:
# Obsah obdelniku # Prisady: sirka = 20 vyska = 30 # Postup: obsah = sirka * vyska print obsah
Na tomto příkladu můžete vidět (ač nepříliš patrnou) podobnost s receptem na šunkový salát. Ale jak to vlastně funguje? Za prvé, řádky začínající znakem # se nazývají komentáře a počítač je ignoruje. Ale používání takovýchto drobných vysvětlení může pomoci čitelnosti programu pro lidi.
Dále, řádkům, které vypadají jako neco = cosi, se říká přiřazení. V případě sirka = 20 říkáme počítači, že od teď by se měla šířka rovnat dvaceti. Co znamená, že „šířka je dvacet“? Znamená to, že proměnná jménem „sirka“ je vytvořena (nebo je opětovně použita, pokud již existuje) a je jí předána hodnota 20. Takže když tuto proměnnou použijeme později, počítač zná její hodnotu. Tím pádem
sirka*vyska
je v podstatě to samé jako
20*30
a to je vypočteno s výsledkem 600, což je přiřazeno proměnné obsah. Poslední příkaz v programu vypíše obsah proměnné obsah, takže to, co vidíte při spuštění programu je prostě
600
Poznámka: V některých jazycích musíte říci počítači, co budete potřebovat za proměnné, hned na začátku programu (podobně, jako je tomu u přísad do salátu) — Python je dost chytrý na to, aby si s proměnnými poradil za chodu.
OK. Nyní umíte vytvářet jednoduché i trošku složitější výpočty. Třeba budete chtít vytvořit program, který bude počítat obsah kruhu namísto obdélníku:
polomer = 30 print polomer * polomer * 3.14
To ale není o moc zajímavější než program s obdélníkem. Nebo alespoň podle mého názoru. Je to jaksi neobratné. Co když budeme chtít znát obsah kruhu o poloměru 31? Jak to počítači sdělit? Je to trošku jako v části receptu na salát: „Smažte 3 až 4 minuty, nebo dokud není šunka hotová.“ Abychom se dozvěděli, zda je šunka hotová, musíme si to zjistit. Potřebujeme zpětnou vazbu, nebo nějaký vstup informací. A jak má počítač znát poloměr našeho kruhu? Také potřebuje vstup… Takže mu můžeme říci, aby si zjistil poloměr:
polomer = input("Jaky je polomer? ")
print polomer * polomer * 3.14
Teď to konečně začíná být zajímavé… input je cosi, čemu se říká funkce. (Za chvíli se naučíte psát vlastní funkce. input je funkce vestavěná do jazyka Python.) Prostým napsáním
input
toho moc nenaděláte. Musíte za něj přidat závorky. input() už pracovat bude — bude čekat, až uživatel zadá poloměr. Verze uvedená výše je poněkud uživatelsky přívětivější, jelikož první vytiskne otázku. Když dáme něco jako tento dotazovací řetězec do závorek volání funkce, říká se tomu předávání parametru funkci. Věc (nebo věci) v závorce je (jsou) parametr(y). V našem případě předáváme otázku jako parametr, takže input ví, co má vypsat předtím, než bude čekat na uživatelovu odpověď.
Jak ale dostat odpověď do proměnné polomer? Funkce input (podobně jako spousta jiných funkcí) po zavolání vrací hodnotu. Tuto hodnotu nemusíme použít, ale v našem případě ji použít chceme. Následující dva příkazy mají zcela odlišné významy:
neco = input cosi = input()
neco nyní obsahuje vstupní funkci samu o sobě (takže je možné použít neco("Kolik je ti let? "); říká se tomu dynamické volání funkce), zatímco cosi obsahuje to, co napsal uživatel.
Nyní dokážeme psát programy pro vykonávání základních úkonů (aritmetických, vypisovacích) a umíme přijímat vstup od uživatele. To je užitečné, ale stále jsme omezování tzv. sekvenčním prováděním příkazů — to znamená, že musí vykonány v přesném pořadí. Valná část receptu na šunkový salát je takto sekvenční nebo lineární. Ale co kdybychom chtěli, aby nám počítač kontroloval smažení šunky? Je-li již tepelně upravená, měla by jít z pánve pryč — jinak by na ní měla ještě nějakou tu minutku zůstat. Jak to vyjádřit?
To, co chceme, je kontrola toku programu. Ten totiž může téct dvěma směry — buď šunku vyndáme z trouby, nebo ji v ní necháme. Můžeme si vybrat, podmínkou je, zda je šunka dostatečně tepelně upravená. Říká se tomu podmíněné provádění. Můžeme to udělat takto:
teplota = input("Jaka je teplota v troube?")
if teplota > 50:
print "Salat je jiz tepelne upraven."
else:
print "Salat potrebuje jeste chvili smazeni."
Smysl by měl být jasný: Jestliže je teplota vyšší než 50 (stupňů Celsia), vypíše se zpráva upozorňující uživatele na to, že šunka je usmažená, jinak je uživatel upozorněn, že by měl salát ještě chvíli smažit.
Poznámka: Odsazování je v Pythonu důležité. Bloky při podmíněném provedení (a v cyklech a definicích funkcí — viz níže) musí být odsazeny (a navíc musí být odsazeny stejným počtem bílých znaků; tabulátor se počítá jako osm mezer), aby interpret mohl určit, kde začínají a kde končí. Díky tomu jsou programy čitelnější i pro lidi.
Vraťme se k našemu výpočtu obsahu. Chápete, co dělá?
# Program pro vypocet obsahu
print “Vitejte v Programu pro vypocet obsahu”
print “–––––––––––––”
print
# Vypis nabidky:
print “Vyberte tvar, prosim:”
print “1 Obdelnik”
print “2 Kruh”
# Ziskani uzivatelovy volby:
tvar = input(“> “)
# Vypocet obsahu:
if tvar == 1:
vyska = input(“Zadejte vysku, prosim: “)
sirka = input(“Zadejte sirku, prosim: “)
obsah = vyska*sirka
print “Obsah je”, obsah
else:
polomer = input(“Zadejte polomer, prosim: “)
obsah = 3.14*(polomer**2)
print “Obsah je”, obsah
Novinky v tomto příkladu:
print způsobí vytisknutí prázdného řádku== kontroluje, jestli jsou si dvě hodnoty rovny, na rozdíl od =, kterým se přiřazuje hodnota z pravé strany do proměnné na levé straně. To je zásadní odlišnost!** slouží v Pythonu k mocnění — druhou mocninu poloměru tedy zapíšeme jako polomer**2.print může vypsat více věcí, stačí je oddělit čárkami. (Na výstupu budou odděleny mezerami.)Program je celkem jednoduchý: Zeptá se na číslo, které určuje, zda uživatel chce spočítat obsah obdélníku, nebo kruhu. Pak je použit výraz if (podmíněné proveddní) pro rozhodnutí, který blok se má použít pro výpočet obsahu. Tyto bloky jsou v podstatě stejné jako ty použité v dřívějších příkladech. Všimněte si, jak dělají komentáře program čitelnějším. První přikázání programování zní: „Budeš používat komentáře.“ Každopádně je to docela dobrý zvyk.
Rozšiřte výše uvedený program tak, aby počítal i obsah čtverce, přičemž uživatel bude muset zadat délku jen jedné strany. Abyste mohli něco takového udělat, musíte vědět jednu věc: Jsou-li možné více než dvě volby, můžete napsat něco jako:
if neco == 1:
# Delej neco...
elif neco == 2:
# Delej neco jineho...
elif neco == 3:
# Delej neco uplne jineho...
else:
# Kdyz vsechno ostatni selze...
Zde tajemné elif znamená v podstatě „else if“ :). Takže pokud bude neco rovno jedné, pak se bude něco dělat, pokud bude neco rovno dvěma, bude se dělat něco jiného,… Můžete přidat do programů i další volby — třeba pro výpočet obsahu trojúhelníků nebo libovolných jiných mnohoúhelníků, je to na vás.
Sekvenční a podmíněné vykonávání příkazů, to jsou jen dva ze tří základních stavebních kamenů programování. Tím třetích je cyklus. V předchozí kapitole jsme navrhli řešení zjišťování, zda je již šunka dostatečně tepelně upravená, bylo to ovšem poněkud nevhodné řešení. Co kdyby šunka nebyla hotová ani v době dalšího zjišťování jejího stavu? Můžeme vůbec vědět, kolikrát bychom to museli zjišťovat? Ve skutečnosti nemůžeme. A neměli bychom. Měli bychom být schopni dát počítači za úkol kontrolování stavu šunky, dokud by nebyla hotová. Jak to uděláme? Uhodli jste ---použijeme cyklus, neboli opakované provádění.
Python zná dva typy cyklů: cykly while a cykly for. Cykly for jsou asi snadnější. Například:
for jidlo in "sunka", "vejce", "rajcata":
print "Miluji", jidlo
To znamená: Pro každý prvek v seznamu "sunka", "vejce", "rajcata" se má vytisknout, že jej milujete. Blok uvnitř cyklu je proveden pro každý prvek jednou, pokaždé, když je aktuální prvek přiřazen do proměnné jidlo (v tomto případě). Jiný příklad:
for cislo in range(1,100):
print "Ahoj, svete!"
print "Zbyva uz jen", 100 - cislo, "cisel..."
print "Ahoj, svete!"
print "To bylo posledni... Uf!"
Funkce range vrací seznam čísel ze zadaného intervalu (včetně prvního a vyjma posledního čísla… V tomto případě [1..99]). Jinými slovy to znamená:
for) každé číslo (cislo) v (in) rozsahu (range) od (a včetně) 1 do (a vyjma) 100. (Co tělo cyklu a následující výrazy ve skutečnosti dělají je ponecháno jako domácí úkol.)To nám ale opravdu nepomůže s naším problémem se smažením. Pokud bychom chtěli šunku zkontrolovat stokrát, bylo by to pěkné řešení; jenže my nevíme, zda je počet kontrol dostatečný, nebo příliš vysoký. Prostě chceme kontrolovat šunku, dokud je nedostatečně tepelně upravená (nebo dokud není dostatečně tepelně upravená — záleží na úhlu pohledu). Takže použijeme cyklus while:
# Program pro smazeni sunky
# Ziskani funkce *sleep*
from time import sleep
print "Zacni, prosim, se smazenim sunky. (Vratim se za tri minuty.)"
# Cekej 3 minuty (tzn. 3*60 sekund)
sleep(180)
print "Jsem zpeeet :)"
# Jak teple je dostatecne teple?
dost_teple = 50
teplota = input("Jak je sunka tepla? ")
while teplota < dost_teple:
print "Malo teple... Jeste chvili smazte...")
sleep(30)
teplota = input("OK. Jak je sunka tepla nyni? ")
print "Je to dost teple — hotovo!"
Novinky v tomto příkladu…
sleep (která spí po zadaný počet sekund) z modulu time, který je distribuován společně s Pythonem. (Můžete si vytvářet i své vlastní moduly…)Napište program, který plynule čte čísla od uživatele a sčítá je dokud součet nedosáhne stovky. Napište jiný program, který načte 100 čísel od uživatele a vypíše jejich součet.
Když chcete získat představu o obsahu knihy, nepřečtete si všechny její stránky — jen se podíváte do obsahu, že ano? Jsou v něm stručně vypsány názvy jednotlivých kapitol. A teď si představte psaní kuchařky. Mnoho receptů, například „Krémová šunka s makaróny“ nebo „Švýcarský šunkový koláč“, může obsahovat spoustu podobných věcí, v tomto případě třeba šunku — jistě byste nechtěli v každém receptu popisovat, jak se dělá šunka. (Ve skutečnosti si sice šunku obvykle sami nevyrábíme, ale sneste tuto nepřesnost, je to přece jen příklad :)) Takže napíšete zvláštní kapitolu o výrobě šunky a v jiných receptech se na ni budete odkazovat. To znamená, že nebudete pokaždé psát celý recept se vším všudy, ale jen se odkážete na příslušnou kapitolu s podrobnostmi jejím jménem. V programování se tomu říká abstrakce.
Už jsme něco takového dělali? Ano. Namísto přesného vysvětlování počítači, jak získat od uživatele nějaký vstup (dobrá, to bychom nedokázali… asi tak jako bychom si těžko dokázali vyrobit šunku, takže… :)), jsme použili input — funkci. Funkce si můžeme dokonce sami vytvářet, je to určitá forma abstrakce.
Řekněme, že chceme najít největší celé číslo, které je menší než zadané kladné číslo. Například pro 2,7 by to bylo 2. Často se tomu říká „celá část“ daného čísla. (Mohli bychom toho dosáhnout pomocí vestavěné funkce Pythonu int, ale mějte se mnou strpení…) Jak to udělat? Mohli bychom otestovat všechny hodnoty větší než nula:
cislo = input("Zadejte cislo: ")
cela_cast = 0
while cela_cast <= cislo:
cela_cast = cela_cast + 1
cela_cast = cela_cast - 1
print "Cela cast cisla", cislo, "je", cela_cast
Všimněte si, že cyklus končí až cela_cast již není menší (nebo rovna) číslu; přidáme k ní příliš mnoho. Musíme tedy nakonec jedničku odečíst. Co kdybychom chtěli použít tuto „celou část“ v komplexním matematickém výrazu? Museli bychom opisovat celý cyklus pro každé číslo, jehož „celou část“ bychom potřebovali. To není moc pěkné… Asi vás napadlo, co bychom mohli udělat místo toho — mohli bychom si vytvořit vlastní funkci nazvanou „celá část“:
def cela_cast(cislo):
vysledek = 0
while vysledek <= cislo:
vysledek = vysledek + 1
vysledek = vysledek - 1
return vysledek
Novinky v tomto příkladu…
def následovaného jménem funkce a požadovanými parametry uvedenými v závorkách.return (které také ukončuje funkci).To, co jsme definovali, můžeme nyní použít:
x = 2.7 y = cela_cast(x)
Poté by hodnota y měla být 2. Je také možné vytvářet funkce s více parametry:
def soucet(x, y):
return x + y
Napište funkci implementující Euklidův algoritmus pro nalezení největšího společného dělitele dvou čísel. Algoritmus funguje takto:
a a b, a je větší než b.b rovno nule:a je změněna na hodnotu b.b je změněna na zbytek po dělení hodnoty a (před změnou) hodnotou b (před změnou).a je největším společným dělitelem čísel.Rady:
a a b jako parametry funkce.a je větší než b.x číslem z se zapíše jako x % z.x, y = y, y + 1. V tomto případě je do x uložena hodnota y (tzn. hodnota y před přiřazením) a hodnota y je zvýšena o jedničku.Jak vám šlo řešení úkolu? Bylo to složité? Stále jste zmateni, co se funkcí týče? Nedělejte si starosti — toto téma ještě neopouštíme.
Druh abstrakce, který jsme použili při vytváření funkcí, se nazývá procedurální abstrakce; v mnoha programovacích jazycích se používá slovo procedura i slovo funkce. Tyto dva koncepty se ve skutečnosti liší, nicméně v Pythonu jsou obě nazývány funkcemi (ostatně se víceméně stejně definují i používají).
Jaký je (v jiných programovacích jazycích) rozdíl mezi funkcemi a procedurami? Jak jste si mohli všimnout v minulé kapitole, funkce vrací hodnotu. Rozdíl tedy spočívá v tom, že procedury žádnou hodnotu nevrací. Často se dělení funkcí na dva typy — na ty, které hodnotu vrací a na ty, které hodnotu nevrací — může hodit.
Funkce, která nevrací hodnotu („procedura“), se používá jako podprogram. Zavoláme funkci a program něco dělá, třeba vyrábí šlehačku. Takovou funkci můžeme použít na více místech, abychom nemuseli znovu psát kód. (Říká se tomu znovupoužití kódu — více na toto téma později.)
Užitečnost takové funkce (nebo procedury) spočívá ve vedlejším efektu — mění se prostředí, v němž funkce běží (například smícháním cukru a smetany a následným šleháním). Podívejme se na příklad:
def ahoj(kdo):
print "Ahoj,", kdo
ahoj("svete")
# vypise "Ahoj, svete"
Vypisování se zde říká vedlejší efekt a jelikož je to to jediné, co funkce dělá, je tato funkce typickou procedurou. Ale… ve skutečnosti tato funkce nemění prostředí, v němž běží, že ne? Jak by to mohla udělat? Vyzkoušejme:
# *spatny* zpusob, jak to udelat
vek = 0
def nastavVek(v):
vek = v
nastavVek(100)
print vek
# vypise "0"
Copak je tady špatně? Problém je, že funkce nastavVek si vytváří svou vlastní lokální proměnnou, která se také jmenuje vek, ale existuje pouze uvnitř funkce nastavVek. Jak tomu zabránit? Můžeme použít něco, čemu se říká globální proměnná.
Poznámka: Globální proměnné se v Pythonu příliš nepoužívají. Vedou totiž ke špatnému strukturování programu, k tzv. špagetovému kódu. Zde je používám jen k vysvětlení komplexnějších záležitostí — jinak se jich, prosím, vyvarujte.
Tím, že řekneme interpreteru, že je proměnná globální (pomocí výrazu jako je global vek), mu řekneme, že má být použita proměnná mimo funkci namísto vytváření nové lokální proměnné. (Globální je tedy opakem k lokální.) Program můžeme přepsat například takto:
# korektni, ale ne zcela spravny postup, jak to udelat
vek = 0
def nastavVek(v):
global vek
vek = v
nastavVek(100)
print vek
# vypise 100
Jakmile si přečtete něco o objektech (níže), zjistíte, že mnohem vhodnější by bylo vytvořit objekt s položkou vek a metodou nastavVek. V kapitole o složitějších datových typech také uvidíte lepší příklady funkcí měnících prostředí, v němž se vyskytují.
Co říci o opravdových funkcích? Co je to ve skutečnosti funkce? Matematické funkce jsou trošku jako „stroje“, které na základě nějakého vstupu vypočítají výsledek. Pro stejný vstup vždy vracejí stejnou hodnotu. Kupříkladu:
def mocnina(x):
return x * x
Je to to samé jako matematická funkce f(x) = x2. Chová se to jako hezká funkce, která závisí jen na svém vstupu, nemění žádným způsobem prostředí, v němž běží.
Nastínil jsem dva způsoby tvorby funkcí: V jednom případě se jedná spíše o proceduru, funkce nevrací žádný výsledek; v druhém případě se v podstatě jedná o matematickou funkci, taková funkce nedělá (plus mínus) kromě vracení výsledku nic jiného. Samozřejmě může existovat něco mezi těmito dvěma extrémy, ale pokud funkce mění své okolí, mělo by být jasné, že to dělá. Lze to naznačit například odlišným pojmenováním funkce — „čistá“ funkce se může jmenovat mocnina, kdežto v názvu hybrida mezi funkcí a procedurou se může vyskytovat rozkazovací způsob, třeba nastavVek.
Nyní již toho víte docela dost: Jak zajistit vstup i výstup programu, jak strukturovat komplikovanější algoritmy (programy), jak provádět aritmetické výpočty; to nejlepší ale stále ještě nepřišlo.
Jaké přísady jsme dosud ve svých programech používali? Čísla a řetězce. Nudné? Přidejme tedy další, zajímavější přísady.
Datové struktury jsou přísady, které strukturují data. (Opravdu velké překvapení…) Obyčejné číslo nevypadá, že by mělo příliš struktury, že? Řekněme ale, že bychom chtěli zahrnout více čísel do jedné přísady — ta by pak měla nějakou strukturu. Můžeme chtít třeba seznam čísel. To není těžké:
[3, 6, 78, 93]
Seznamy jsem zmínil už v kapitole o cyklech, ale moc jsem toho o nich neprozradil. Takže už jste viděli, jak takový seznam vytvořit; je to prostě seznam prvků oddělených čárkami, uzavřený v hranatých závorkách.
Podívejme se nyní na příklad ukazující výpočet prvočísel (čísel dělitelných jen sebou samými a jedničkou):
# Vypocet vsech prvocisel mensich nez 1000
# (Neni to nejlepsi zpusob, ale...)
vysledek = [1]
kandidati = range(3, 1000)
zaklad = 2
soucin = zaklad
while kandidati:
while soucin < 1000:
if soucin in kandidati:
kandidati.remove(soucin)
soucin = soucin + zaklad
vysledek.append(zaklad)
zaklad = kandidati[0]
soucin = zaklad
del kandidati[0]
vysledek.append(zaklad)
print vysledek
Novinky v tomto příkladu…
range ve skutečnosti vrací obyčejný seznam. (Zahrnuje první číslo z intervalu, poslední nikoliv.)true (pravda), prázdný seznam odpovídá nepravdě — false. Takže while kandidati ve skutečnosti znamená „dokud není seznam pojmenovaný kandidati prázdný“, respektive „dokud jsou nějací kandidáti“.if nejakyPrvek in nejakySeznam pro kontrolu, zda je prvek obsažen v seznamu.nejakySeznam.remove(nejakyPrvek) pro odstranění prvku nejakyPrvek ze seznamu nejakySeznam.nejakySeznam.append(neco). Sice můžete použít i operátor +
(například nejakySeznam = nejakySeznam + [neco]), ale není to to samé.0) uvedeného v hranatých závorkách za jménem seznamu. Takže nejakySeznam[3] je čtvtých prvkem seznamu nejakySeznam. (Více o tomto tématu níže.)del. To může být také (jako v tomto případě) ke smazání prvku seznamu. Tedy del nejakySeznam[0] smaže první prvek seznamu nejakySeznam. Pokud bylo obsahem seznamu [1, 2, 3] před mazáním, po mazání to bude [2, 3].Před vysvětlením tajemství okolo seznamů ještě objasním výše uvedený příklad.
Příklad výše je variací na velice starý algoritmus nazývaný „Erasthenovo síto“. Uvažujme množinu (v našem případě seznam) potenciálních prvočísel a poté z něj systematicky odstraňujme čísla, o nichž víme, že nejsou prvočísly. Jak to víme? Tato čísla jsou součinem dvou jiných čísel.
Začínáme se seznamem čísel [2..999] — víme, že jednička je prvočíslo (nebo není, záleží na tom, koho se zeptáte) a chceme znát všechna prvočísla menší než tisíc. (Ve skutečnosti je náš seznam jen [3..999], ale dvojka je také kandidátem na prvočíselnost, je to náš první zaklad.) Máme také seznam nazvaný vysledek, který v každé chvíli obsahuje aktuální seznam výsledků. Na začátku obsahuje jen jedničku. Ještě máme proměnnou zaklad. V každé iteraci („kole“) algoritmu odstraníme všechna čísla, která jsou násobky tohoto základu (nejmenšího kandidáta na prvočíselnost). Po každé iteraci víme, že nejmenší zbylé číslo je prvočíslo (všechna čísla, která byla násobkem menších čísel již byla odstraněna — chápete?). Přidáme jej k výsledkům, nastavíme jej jako základ a odstraníme jej ze seznamu potenciálních prvočísel (abychom s ním opět nepočítali). Jakmile bude seznam kandidátů na prvočíselnost prázdný, seznam výsledků bude obsahovat všechna prvočísla. Chytré, ne?
Věci k zamyšlení: Co je zvláštního na první iteraci? V ní je základem dvojka, která je odstraněna z „prosívání“? Proč? Proč se to neděje ostatním základům? Můžeme si být jisti, že soucin je v seznamu potenciálních prvočísel vždy, když jej chceme odstranit? Proč?
Co nyní? Jistě… Indexování. A rozřezávání. To jsou způsoby, jak v Pythonu získat jednotlivé prvky seznamu. Už jste viděli v akci obyčejné indexování. Je to docela jednoduché. Už jsem o tom uvedl vše vyjma jedné věci: Záporné indexy slouží k přistupování k prvkům seznamu od jeho konce. Takže nejakySeznam[-1] vrací poslední prvek seznamu nejakySeznam, nejakySeznam[-2] vrací předposlední prvek a tak dále.
Rozřezávání by pro vás mělo být nové. Je podobné indexování, ale jeho výsledkem není jen jeden prvek seznamu, nýbrž hned několik prvků seznamu. Jak se to dělá? Takto:
jidlo = ["sunka", "sunka", "vejce", "salamy", "sunka"] print jidlo[2:4] # Vypise "['vejce', 'salamy']"
Pokud bylo někdy nějaké slovní spojení neustále omíláno stále dokola, pak to bylo nepochybně „objektově orientované programování“.
Jak název této kapitoly naznačuje, objektově orientované programování je jen jiným způsobem, jak abstrahovat detaily. Procedury abstrahují jednoduché výroky do komplexnějších operací tím, že jim dávají jméno. V OOP nemanipulujeme pouze s operacemi, ale rovnou s objekty. (To je ale překvapení, že?) Pokud bychom psali třeba program na smažení šunky, namísto psaní spousty procedur pro vypořádání se s teplotou, časem, přísadami,… bychom vše sdružili do jednoho objektu pro šunku. Možná bychom mohli mít i objekty pro troubu, hodiny,… Pak by věci jako teplota byly položkami objektu pro šunku, zatímco čas by spadal pod zvláštní objekt pro čas. Aby náš program něco dělal, mohli bychom své objekty naučit metodám; například trouba by mohla umět péct šunku atd.
Takže jak to uděláme v Pythonu? Objekt nemůžeme udělat přímo. Namísto vytváření trouby vytváříme recept, který udává, jaké trouby bývají. Tento recept popisuje třídu objektů, které nazýváme troubami. Velice jednoduchá třída pro troubu by mohla být:
class Trouba:
def vlozSunku(self, sunka):
self.sunka = sunka
def vratSunku(self):
return self.sunka
Nevypadá to divně?
Novinky v tomto příkladu…
class.self (nebo tak nějak…). Důvod (snad) vyplyne na povrch za moment.mojeSunka.teplota = 2 nebo dilbert.bud_prijemny().Tipuji, že stále je ohledně příkladu ještě něco nejasného. Například ta záležitost ohledně self. A když už máme recept na objekt (například třídu), jak vytvoříme konkrétní objekt?
Nejprve se vypořádejme s druhým problémem. Objekt vytvoříme voláním jména třídy jakoby to byla funkce:
mojeTrouba = Trouba()
mojeTrouba nyní obsahuje objekt Trouba, který se obvykle nazývá instance třídy Trouba. Předpokládejme, že jsme si vytvořili i třídu Sunka; pak můžeme udělat něco takového:
mojeSunka = Sunka() mojeTrouba.vlozSunku(mojeSunka)
mojeTrouba.sunka by nyní měla obsahovat objekt mojeSunka. Jak to? Protože když voláme nějakou metodu objektu, první parametr, obvykle nazývaný self, vždy obsahuje objekt samotný. (Chytré, ne?) Takže řádek self.sunka = sunka nastavuje položku sunka konkrétního objektu Trouba na hodnotu parametru sunka. Všimněte si, že se jedná o dvě různé věci, ačkoliv se v tomto příkladu obě jmenují sunka.
Zde je velice stručná verze algoritmu:
def eukleides(a, b):
while b:
a, b = b, a % b
return a
[1] Recept na slavnostní šunkový salát podle digitální kuchařky Hormel Foods.