5. Podprogramy¶
Funkcie¶
Doteraz sme pracovali so štandardnými funkciami, napríklad
vstup a výstup
input()
aprint()
aritmetické funkcie
abs()
around()
generovanie postupnosti čísel pre for-cyklus
range()
Všetky tieto funkcie niečo vykonali (vypísali, prečítali, vypočítali, …) a niektoré z nich vrátili nejakú hodnotu, ktorú sme mohli ďalej spracovať. Tiež sme videli, že niektoré majú rôzny počet parametrov, prípadne sú niekedy volané bez parametrov.
Okrem toho sme pracovali aj s funkciami, ktoré boli definované v iných moduloch:
keď napíšeme
import random
, môžeme pracovať, napríklad s funkciamirandom.randint()
arandom.randrange()
keď napíšeme
import math
, môžeme pracovať, napríklad s funkciamimath.sin()
amath.cos()
keď napíšeme
import tkinter
, môžeme pracovať, napríklad s funkciamitkinter.Canvas()
atkinter.mainloop()
Všetky tieto a tisícky ďalších v Pythone naprogramovali programátori pred nejakým časom, aby nám neskôr zjednodušili samotné programovanie. Vytváranie vlastných funkcií pritom vôbec nie je komplikované a teraz sa to naučíme aj my.
Ako prvý príklad zapíšme takúto definíciu funkcie:
def vypis():
print('**********')
print('**********')
Zadefinovali sme funkciu s menom vypis
, pričom telo funkcie obsahuje dva príkazy na výpis riadkov s hviezdičkami. Celý blok príkazov je odsunutý o 4 medzery rovnako ako sme odsúvali príkazy v cykloch a aj v podmienených príkazoch. Definícia tela funkcie končí vtedy, keď sa objaví riadok, ktorý už nie je odsunutý. Touto definíciou sa ešte žiadne príkazy z tela funkcie nevykonávajú. Na to potrebujeme túto funkciu zavolať.
Zavolajme funkciu vypis
v príkazovom režime:
>>> vypis()
**********
**********
>>>
Vidíme, že sa vykonali oba príkazy z tela funkcie a potom Python ďalej čaká na ďalšie príkazy. Zapíšme volanie funkcie aj s jej definíciou priamo do skriptu (teda v programovom režime):
def vypis():
print('**********')
print('**********')
print('hello')
vypis()
print('* Python *')
vypis()
Skôr, ako to spustíme, si uvedomme, čo sa udeje pri spustení:
zapamätá sa definícia funkcie v premennej
vypis
vypíše sa slovo
'hello'
zavolá sa funkcia
vypis()
vypíše riadok s textom
'* Python *'
znovu sa zavolá funkcia
vypis()
A teraz to spustíme:
hello
**********
**********
* Python *
**********
**********
Zapíšme teraz presné kroky, ktoré sa vykonajú pri volaní funkcie:
preruší sa vykonávanie práve bežiaceho programu (Python si presne zapamätá miesto, kde sa to stalo)
skočí sa na začiatok volanej funkcie
postupne sa vykonajú všetky príkazy
keď sa príde na koniec funkcie, zrealizuje sa návrat na zapamätané miesto, kde sa prerušilo vykonávanie programu a pokračuje sa vo vykonávaní ďalších príkazov za volaním funkcie
Pre volanie funkcie sú veľmi dôležité okrúhle zátvorky. Bez nich to už nie je volanie, ale len zisťovanie referencie na hodnotu, ktorá je priradená pre toto meno. Napríklad:
>>> vypis()
**********
**********
>>> vypis
<function vypis at 0x0205CB28>
Ak by sme namiesto volania funkcie takto zapísali len meno funkcie bez zátvoriek, ale v skripte (teda nie v interaktívnom režime), táto hodnota referencie by sa nevypísala, ale odignorovala. Toto býva dosť častá chyba začiatočníkov, ktorá sa ale ťažšie odhaľuje.
Ak zavoláme funkciu, ktorú sme ešte nedefinovali, Python vyhlási chybu, napríklad:
>>> vipis()
...
NameError: name 'vipis' is not defined
Samozrejme, že môžeme volať len definované funkcie.
>>> vypis()
**********
**********
>>> vypis = 'ahoj' # tu sme zmenili obsah premennej vypis
>>> vypis
'ahoj'
>>> vypis()
...
TypeError: 'str' object is not callable
Hodnotou premennej vypis
je už teraz znakový reťazec, a ten sa „nedá zavolať“, t.j. nie je „callable“ (tento objekt nie je zavolateľný ako funkcia).
Funkcie kreslia do grafickej plochy¶
Napíšme teraz funkciu, ktorá do grafickej plochy na náhodnú pozíciu napíše nejaký text, napríklad 'PYTHON'
:
def kresli_text():
x = random.randint(50, 330)
y = random.randint(20, 240)
canvas.create_text(x, y, text='PYTHON')
Aby sme túto funkciu mohli zavolať, musí už exitovať randint
(zrejme z modulu random
) aj canvas
(vznikne pomocou modulu tkinter
), teda
import tkinter
import random
def kresli_text():
x = random.randint(50, 330)
y = random.randint(20, 240)
canvas.create_text(x, y, text='PYTHON')
canvas = tkinter.Canvas()
canvas.pack()
for i in range(20):
kresli_text()
tkinter.mainloop()
V tejto malej ukážke vidíme tieto novinky:
v tele funkcie môžeme používať premenné, ktoré sú definované mimo tela funkcie (
random.randint
acanvas
) - neskôr uvidíme, že im budeme hovoriť globálne premennév tele funkcie sme do dvoch premenných
x
ay
priradili nejaké hodnoty a ďalej sme ich používali v ďalšom príkaze funkcie - neskôr uvidíme, že im budeme hovoriť lokálne premenné
Parametre funkcií¶
Hotové funkcie, s ktorými sme doteraz pracovali, napríklad print()
alebo random.randint()
, mali aj parametre, vďaka čomu riešili rôzne úlohy. Parametre slúžia na to, aby sme mohli funkcii lepšie oznámiť, čo špecifické má urobiť: čo sa má vypísať, z akého intervalu má vygenerovať náhodné číslo, akú úsečku má nakresliť, prípadne akej farby, …
Môžeme napríklad zapísať:
def vypis_hviezdiciek(pocet):
print('*' * pocet)
V prvom riadku definície funkcie (hlavička funkcie) pribudla jedna premenná pocet
- parameter. Táto premenná vznikne automaticky pri volaní funkcie, preto musíme pri volaní oznámiť hodnotu tohto parametra. Volanie zapíšeme:
>>> vypis_hviezdiciek(30)
******************************
>>> for i in range(1, 10):
vypis_hviezdiciek(i)
*
**
***
****
*****
******
*******
********
*********
Pri volaní sa „skutočná hodnota“ priradí do parametra funkcie (premenná pocet
).
Už predtým sme popísali mechanizmus volania funkcie, ale to sme ešte nepoznali parametre. Teraz doplníme tento postup o spracovanie parametrov. Najprv trochu terminológie:
pri definovaní funkcie v hlavičke funkcie uvádzame tzv. formálne parametre: sú to nové premenné, ktoré vzniknú až pri volaní funkcie
pri volaní funkcie musíme do zátvoriek zapísať hodnoty, ktoré sa stanú tzv. skutočnými parametrami: tieto hodnoty sa pri volaní priradia do formálnych parametrov
Mechanizmus volania vysvetlíme na volaní vypis_hviezdiciek(30)
:
zapamätá sa návratová adresa volania
vytvorí sa nová premenná
pocet
(formálny parameter) a priradí sa do nej hodnota skutočného parametra30
vykonajú sa všetky príkazy v definícii funkcie (telo funkcie)
zrušia sa všetky premenné, ktoré vznikli počas behu funkcie
riadenie sa vráti na miesto, kde bolo volanie funkcie
Zapíšme novú funkciu cerveny_kruh()
, ktorá bude mať dva parametre: súradnice stredu kruhu. Funkcia nakreslí kruh s polomerom 10 a s daným stredom:
def cerveny_kruh(x, y):
canvas.create_oval(x - 10, y - 10, x + 10, y + 10, fill='red')
a môžeme ju zavolať napríklad takto:
import tkinter
def cerveny_kruh(x, y):
canvas.create_oval(x - 10, y - 10, x + 10, y + 10, fill='red')
canvas = tkinter.Canvas()
canvas.pack()
for x in range(30, 350, 25):
for y in range(20, 240, 15):
cerveny_kruh(x, y)
tkinter.mainloop()
Aj v tomto príklade si popíšme Mechanizmus volania funkcie:
zapamätá sa návratová adresa volania
vytvoria sa dve nové premenné
x
ay
(formálne parametre) a priradia sa do nej hodnoty skutočných parametrov30
a20
(prvé volanie funkcie)vykonajú sa všetky príkazy v definícii funkcie (telo funkcie)
zrušia sa všetky premenné, ktoré vznikli počas behu funkcie, teda
x
ajy
riadenie sa vráti na miesto, kde bolo volanie funkcie
Už vieme, že priraďovací príkaz vytvára premennú a referenciou ju spojí s nejakou hodnotou. Premenné, ktoré vzniknú počas behu funkcie, sa stanú lokálnymi premennými: budú existovať len počas tohto behu a po skončení funkcie, sa automaticky zrušia. Aj parametre vznikajú pri štarte funkcie a zanikajú pri jej skončení: tieto premenné sú pre funkciu tiež lokálnymi premennými.
V nasledovnom príklade funkcie vypis_sucet()
počítame a vypisujeme súčet čísel od 1 po zadané n
:
def vypis_sucet(n):
sucet = 1
print(1, end=' ')
for i in range(2, n + 1):
sucet = sucet + i
print('+', i, end=' ')
print('=', sucet)
Pri volaní funkcie sa pre parameter n
= 10 vypíše:
>>> vypis_sucet(10)
1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = 55
Počas behu vzniknú 2 lokálne premenné (sucet
a i
) a jeden parameter, ktorý je pre funkciu tiež lokálnou premennou:
n
vznikne pri štarte funkcie aj s hodnotou 10sucet
vznikne pri prvom priradenísucet = 1
i
vznikne pri štarte for-cyklu
Po skončení behu funkcie sa všetky tieto premenné automaticky zrušia.
Pozrime sa na lokálne premenné, ktoré vznikajú vo funkcii nahodne_kruhy(n, farba)
:
def nahodne_kruhy(n, farba):
for i in range(n):
x = random.randint(50, 330)
y = random.randint(20, 240)
canvas.create_oval(x - 10, y - 10, x + 10, y + 10, fill=farba)
Napríklad:
import tkinter
import random
def nahodne_kruhy(n, farba):
for i in range(n):
x = random.randint(50, 330)
y = random.randint(20, 240)
canvas.create_oval(x - 10, y - 10, x + 10, y + 10, fill=farba)
canvas = tkinter.Canvas()
canvas.pack()
nahodne_kruhy(100, 'red')
nahodne_kruhy(50, 'blue')
nahodne_kruhy(10, 'yellow')
tkinter.mainloop()
Program postupne nakreslí na náhodné pozície 100 červených, 50 modrých a 10 žltých kruhov.
Všimnite si vo funkcii nahodne_kruhy()
tri lokálne premenné (i
, x
, y
) a dva parametre (n
, farba
), ktoré sú pre funkciu tiež lokálnymi premennými.
Menný priestor¶
Aby sme lepšie pochopili, ako naozaj fungujú lokálne premenné, musíme rozumieť, čo to je a ako funguje menný priestor (namespace). Najprv trochu ďalšej terminológie: všetky identifikátory v Pythone sú jedným z troch typov (Python má pre identifikátory 3 rôzne tabuľky mien):
štandardné, napríklad
int
,print
, …hovorí sa tomu builtins
globálne - definujeme ich na najvyššej úrovni mimo funkcií, napríklad funkcie
vypis_hviezdiciek
,vypis_sucet
,nahodne_kruhy
, alebo aj premennérandrint
,tkinter
,canvas
(zrejmetkinter
je referenciou na importovaný modul)hovorí sa tomu main
lokálne - vznikajú počas behu funkcie
Tabuľka štandardných mien (builtins) je pre celý program len jedna, tiež tabuľka globálnych mien (main) je len jedna, ale každá funkcia má svoju „súkromnú“ lokálnu tabuľku mien, ktorá vznikne pri štarte (zavolaní) funkcie a zruší sa pri konci vykonávania funkcie.
Keď na nejakom mieste použijeme identifikátor, Python ho najprv hľadá (v tzv. menných priestoroch):
v lokálnej tabuľke mien, ak tam tento identifikátor nenájde, hľadá ho
v globálnej tabuľke mien, ak tam tento identifikátor nenájde, hľadá ho
v štandardnej tabuľke mien
Ak nenájde v žiadnej z týchto tabuliek, hlási chybu NameError: name 'identifikátor' is not defined
.
Príkaz (štandardná funkcia) dir()
vypíše tabuľku globálnych mien. Hoci pri štarte Pythonu by táto tabuľka mala byť prázdna, obsahuje niekoľko špeciálnych mien, ktoré začínajú aj končia znakmi '__'
:
>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__',
'__package__', '__spec__']
Keď teraz vytvoríme nejaké nové globálne mená, objavia sa aj v tejto globálnej tabuľke:
>>> premenna = 2015
>>> def funkcia():
... pass
>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__',
'__package__', '__spec__', 'funkcia', 'premenna']
Podobne sa vieme dostať aj k tabuľke štandardných mien (builtins):
>>> dir(__builtins__)
['ArithmeticError', 'AssertionError', 'AttributeError', ...
Takto sa vypíšu všetky preddefinované mená. Vidíme medzi nimi, napríklad 'int'
, 'print'
, 'range'
, 'str'
, …
S týmito tabuľkami súvisí aj príkaz na zrušenie premennej.
Ukážme to na príklade: identifikátor print
je menom štandardnej funkcie (v štandardnej tabuľke mien). Ak v priamom režime (čo je globálna úroveň mien) do premennej print
priradíme nejakú hodnotu, toto meno vznikne v globálnej tabuľke:
>>> print('ahoj')
ahoj
>>> print=('ahoj') # do print sme priradili nejakú hodnotu
>>> print
'ahoj'
>>> print('ahoj')
...
TypeError: 'str' object is not callable
Teraz už print
nefunguje ako funkcia na výpis hodnôt, ale len ako obyčajná globálna premenná. Ale v štandardnej tabuľke mien print
stále existuje, len je táto premenná prekrytá globálnym menom. Python predsa najprv prehľadáva globálnu tabuľku a až keď sa tam nenájde, hľadá sa v štandardnej tabuľke. A ako môžeme vrátiť funkčnosť štandardnej funkcie print
? Stačí vymazať identifikátor z globálnej tabuľky:
>>> del print
>>> print('ahoj')
ahoj
Vymazaním globálneho mena print
ostane definovaný len identifikátor v tabuľke štandardných mien, teda opäť začne fungovať funkcia na výpis hodnôt.
Pozrime sa teraz na prípad, keď sa v tele funkcie bude nachádzať volanie inej funkcie (tzv. vnorené volanie), napríklad:
def vypis_hviezdiciek(pocet):
print('*' * pocet)
def trojuholnik(n):
for i in range(1, n + 1):
vypis_hviezdiciek(i)
Pri ich definovaní v globálnom mennom priestore vznikli dva identifikátory: vypis_hviezdiciek
a trojuholnik
. Zavoláme funkciu trojuholnik
:
>>> trojuholnik(5)
Najprv sa pre túto funkciu vytvorí jej menný priestor (lokálna tabuľka mien) s dvomi lokálnymi premennými: n
a i
. Teraz pri každom (vnorenom) volaní vypis_hviezdiciek(i)
sa pre túto funkciu:
vytvorí nový menný priestor s jedinou premennou
pocet
vykoná sa príkaz
print()
nakoniec sa zruší jej menný priestor, t.j. zanikne premenná
pocet
Môžeme to odkrokovať pomocou http://www.pythontutor.com/visualize.html#mode=edit (zapneme voľbu Python 3.6
alebo Python 3.11
):
najprv do editovacieho okna zapíšeme nejaký program, napríklad:
spustíme vizualizáciu pomocou tlačidla Visualize Execution a potom niekoľkokrát tlačíme tlačidlo Forward >
Všimnite si, že v pravej časti tejto stránky sa postupne zobrazujú menné priestory (tu sa nazývajú frame):
najprv len globálny priestor s premennými
vypis_hviezdiciek
atrojuholnik
potom sa postupne objavujú a aj miznú lokálne priestory týchto dvoch funkcií - na obrázku vidíme oba tieto menné priestory tesne pred ukončením vykonávania funkcie
trojuholnik
s parametrom2
Cvičenia¶
Na prednáške si sa zoznámil s funkciou
nsd(a, b)
, ktorá počítala najväčší spoločný deliteľ dvoch čísel. Inšpiruj sa touto funkciou a napíš funkciunsn(a, b)
, ktorá vypočíta najmenší spoločný násobok dvoch čísel. Napríklad pre volania:a, b = 129, 162 print(f'nsn({a}, {b}) =', nsn(a, b)) a, b = 60, 168 print(f'nsn({a}, {b}) =', nsn(a, b))
dostaneme výstup:
nsn(129, 162) = 6966 nsn(60, 168) = 840
Na prednáške si sa zoznámil s funkciou
fibonacci(n)
, ktorá počítalan
-tý člen fibonacciho postupnosti. Napíš funkciufibonacci_medzi(od, do)
, ktorá vypíše (pomocouprint
) všetky fibonacciho čísla z daného intervalu<od, do>
. Táto funkcia by mala obsahovať len jeden while-cyklus (okrem priradení aif
). Napríklad pre volania:fibonacci_medzi(10, 100) fibonacci_medzi(1000, 3000)
dostaneme výstup:
13 21 34 55 89 1597 2584
Na prednáške si sa zoznámil s funkciou
je_prvocislo(cislo)
, ktorá pomocou funkciepocet_delitelov(cislo)
zisťovala, či je danécislo
prvočíslo. Oprav funkciuje_prvocislo(cislo)
tak, aby nevyužívalapocet_delitelov(cislo)
, ale vo while-cykle zisťovala, či neexistuje aspoň jeden deliteľ v intervale<2, odmocnina>
. Funkcia sa bude postupne snažiť nájsť takého deliteľa daného čísla, ktorého druhá mocnina nie je väčšia ako dané číslo. Napríklad, číslo25
bude postupne deliť2
,3
,4
,5
(pre všetky ich druhá mocnina nie je väčšia ako25
) a na5
skončí, lebo delí25
. Číslo37
sa tiež pokúsi deliť2
,3
,4
,5
,6
(žiadne z nich nie je deliteľom) a keďže pre všetky väčšie je ich druhá mocnina väčšia ako37
, vyhlásime37
za prvočíslo. Okrem funkcieje_prvocislo(cislo)
napíš aj funkciudvojicky(od, do)
, ktorá v danom intervale<od, do>
nájde všetky prvočíselné dvojičky (ich rozdiel je 2). Napríklad:>>> dvojicky(3, 50) 3 5 5 7 11 13 17 19 29 31 41 43 >>> dvojicky(1000000, 1000300) 1000037 1000039 1000211 1000213 1000289 1000291
Napíš funkciu
dom(x, y, vel1, vel2)
, ktorá nakreslí domček: štvorec má ľavý dolný roh(x, y)
a veľkosť strany jevel1
, trojuholník má výškuvel2
a základňuvel1
. Oba sú zafarbené rôznymi náhodnými farbami. Napríklad pre volanie:x, y = 10, 150 while x < 330: v = random.randint(20, 50) dom(x, y, v, random.randint(v // 2, v)) x += v
by sa nakreslilo:
Na prednáške sa pomocou farebných bodiek kreslil červený mesiac na modrom pozadí. Využívala sa pritom funkcia
vzd
. Napíš funkciufarebne_bodky(r, x1, y1, x2, y2, x3, y3)
, ktorá na podobnom princípe grafickú plochu vybodkuje podľa týchto pravidiel: ak by sme nakreslili tri rovnako veľké kruhy s polomeromr
ale s rôznymi stredmi(x1, y1)
,(x2, y2)
,(x3, y3)
, tieto by sa mohli čiastočne prekrývať. Bodky budeš farbiť tak, že tie oblasti, v ktorých nie je žiaden kruh alebo sa prekrývajú práve 2 kruhy zafarbíš na modro, ostatné oblasti budú žlté. Napríklad pre volanie:farebne_bodky(80, 120, 120, 180, 110, 160, 170)
by sa nakreslilo:
Napíš funkciu
stv(riadok, stlpec, farba='white')
, ktorá nakreslí farebný štvorec do myslenej štvorcovej siete, v ktorej je každé políčko veľké 30x30. Ľavý horný roh najľavejšieho horného štvorca má súradnice(5, 5)
. Napríklad pre volanie:for i in range(8): for j in range(12): if i == j: stv(i, j) else: stv(i, j, nahodna_farba())
by sa nakreslilo:
Napíš funkciu
rgb
(z prednášky) a pomocou nej zafarbi štvorce takto: ľavý horný štvorec má farburgb(255, 0, 0)
a pravý dolný skororgb(255, 255, 0)
, farba v ostatných štvorcoch plynulo prechádza - čím je štvorec bližšie k pravému dolnému rohu, tým je bližšie k žltej:
Vektor si môžeme predstaviť ako úsečku, ktorá je daná jedným vrcholom
(x, y)
, dĺžkou a uhlom. Uvedom si, že koncové body takéhoto vektora ležia na kružnici s polomerom dĺžka a daným stredom (bodom(x, y)
). Úsečku nakreslíme tak, aby mala tvar šípky (docreate_line
pridáme pomenovaný parameterarrow='last'
). Napíš funkciuvektor(x, y, dlzka, uhol)
. Otestuj, napríklad takto:for i in range(10): vektor(random.randint(50, 300), random.randint(50, 200), random.randint(10, 80), random.randint(0, 359))
a môžeš dostať:
Napíš funkciu
vybodkuj_usecku(x1, y1, x2, y2, n)
, ktorá nakreslí úsečku z bodu(x1, y1)
do bodu(x2, y2)
. Túto úsečku nekreslí pomocoucreate_line
, ale pomocoun
bodiek, t.j. malých modrých kruhov s polomerom3
. Parametern
je minimálne2
a vtedy sa nakreslia len dve bodky v koncových vrcholoch úsečky. Pre kontrolu najprv vykreslíme originálnu úsečku šedou farbou. Otestuj, napríklad:canvas.create_line(100, 80, 280, 120, fill='lightgray', width=11) vybodkuj_usecku(100, 80, 280, 120, 20) canvas.create_line(280, 120, 150, 200, fill='lightgray', width=11) vybodkuj_usecku(280, 120, 150, 200, 10) canvas.create_line(150, 200, 100, 80, fill='lightgray', width=11) vybodkuj_usecku(150, 200, 100, 80, 8)
dostaneš:
Napíš funkciu
n_uholnik(n, x0, y0, r)
, ktorá nakreslí pravidelnýn
-uholník. Tento n-uholník bude vpísaný v myslenej kružnici so stredom(x0, y0)
a s polomeromr
. Napríklad pre volanie:n_uholnik(3, 50, 50, 45) n_uholnik(4, 150, 50, 45) n_uholnik(5, 250, 50, 45) n_uholnik(6, 50, 150, 45) n_uholnik(7, 150, 150, 45) n_uholnik(8, 250, 150, 45)
by sa malo nakresliť:
Napíš funkciu
n_hviezda(n, x0, y0, r, k=2)
, ktorá pracuje na rovnakom princípe akon_uholnik(n, x0, y0, r)
z predchádzajúcej úlohy. V tomto prípade sa ale nespájajú úsečkami najbližšie vrcholyn
-uholníka, ale parameterk
určuje, o koľko vrcholov sa presunieme pre každú úsečku. Napríkladn_hviezda(5, 50, 50, 45, 2)
označuje, že sa budú spájať vrcholy5
-uholníka takto: 0. vrchol s 2., potom 2. vrchol s 4., potom 4. s 1., 1. vrchol so 3. a na koniec (piata úsečka) 3. vrchol s 0. Zrejme prek=1
by sa kreslili pôvodné n-uholníky. Napríklad pre volanie:n_hviezda(5, 50, 50, 45) n_hviezda(7, 150, 50, 45) n_hviezda(7, 250, 50, 45, 3) n_hviezda(9, 50, 150, 45) n_hviezda(9, 150, 150, 45, 4) n_hviezda(11, 250, 150, 45, 4)
dostaneme:
Aj nasledovná funkcia
n_spirala(n, x0, y0, r)
vychádza z riešenia funkcien_uholnik(n, x0, y0, r)
. V tomto prípade sa nebude kresliťn
-uholník, ale špirála. Každá úsečka tu bude spájať dva vrcholy lenže na stále sa zväčšujúcej kružnici so stredom(x0, y0)
. Začína sa na kružnici s polomerom5
. Prvý vrchol sa spojí s nasledujúcim ale na kružnici s polomerom o2
väčším. Takto sa pokračuje, až kým by nebol polomer väčší akor
. Napríklad pre volanie:n_spirala(5, 190, 130, 125)
dostaneš:
A pre volania:
n_spirala(3, 50, 50, 45) n_spirala(4, 150, 50, 45) n_spirala(5, 250, 50, 45) n_spirala(6, 50, 150, 45) n_spirala(7, 150, 150, 45) n_spirala(8, 250, 150, 45)
dostaneš:
Napíš funkcie
rucicka(uhol, dlzka, hrubka, farba)
ahodinky(hod, min, sek)
, pomocou ktorých nakreslíme ručičkové hodinky. Funkciarucicka
nakreslí len jednu ručičku ako úsečku z bodu(190, 130)
pod daným uhlom, danej farby a hrúbky (podobne ako sa kreslil vektor v 15. úlohe). Funkciahodinky
nakreslí ciferník (stačí kruh s polomerom 100) a tri ručičky pre hodiny (dĺžka60
, hrúbka10
, farba'gray'
), pre minúty (dĺžka70
, hrúbka6
, farba'black'
), pre sekundy (dĺžka80
, hrúbka2
, farba'red'
). Napríklad volanie:hodinky(8, 55, 10)
by nakreslilo:
Ak by si hodinky
zavolal
takto:import time while True: canvas.delete('all') h, m, s = time.localtime()[3:6] hodinky(h, m, s) canvas.update() canvas.after(1000)
ukazovali by aktuálny čas.