1 Modulaarsus ja koodistruktuur¶
1.1 Modulaarne programmeerimine¶
Suuremate programmide lähtekoodi pole otstarbekas salvestada ühte faili. Tarkvara paremaks haldamiseks ja koodide taaskasutuse võimaldamiseks on programmi lähtekood tihti jaotatud erinevatesse failidesse.
- Paljude tänapäeva programmide taga on meeletu hulk koodi. Probleemi ja sellele vastav lahendus jagatakse osadeks.
- Kui olemasolevad alaüksused on ikka liiga keerulised, siis jagatakse need omakorda osadeks jne, kuni saadakse paraja suurusega ülesanded, mida programmeerija suudab oma peas piisava täpsusega hallata.
- Loodud alaüksused ja neile vastavad lahendused (st. programmiosad) peavad üksteisest võimalikult vähe sõltuma, vastasel juhul peab programmeerija mõtlema mitmele ülesandele korraga.
- Funktsioonide lokaalne skoop võimaldab vajadusel funktsiooni sisu ümber kirjutada ilma, et see põhjustaks ootamatusi ülejäänud süsteemis.
1.2 Projekti koodi loetavus¶
Mõned inimesed arvavad, et kui kood töötab, siis kodeerija töö sellega lõppeb. Tõenäoliselt need inimesed ei saa kunagi headeks programmeerijateks. Kuna programmeerimine nõuab tihti rühmatööd, peab kood olema lisaks autorile ka teistele arusaadav. Isegi projekti üksi arendades võib olla kogu protsess drastiliselt raskendatud, kui sa ei jälgi koodi modulaarsuse ja struktureerituse reegleid.
1.3 Moodul¶
Pythoni moodul on .py laiendiga fail, mis sisaldab Pythoni programmeerimiskeeles kirjutatud lähekoodi (funktsioonide, protseduuride, muutujate/atribuutide ja klasside definitsioone, jne). Mooduli mõistet mainisime esimest korda Loengus 8.
- Pythoni mooduli nimi on faili nimi ilma selle laiendita, nt.
foo.pykorral on mooduli nimifoo - .pyc, .pyo $-$ Pythoni ettekompileeritud ja optimiseeritud koodid .py failist
- .so (Linux), .dll (Windows) $-$ Pythoni laiendusmoodulid (kompileeritud teegid)
Tänases loengus: Alustame enda loodud moodulitega ja siis proovime importida Pythoni standardteegi mooduleid ning lõpuks ka kolmandate osapoolte mooduleid ja teeke (suuremad koodi kogumid).
2 Enda loodud moodulite ja pakettide import¶
2.1 Töökaust¶
Paiguta programmi mooduli failid samasse kausta $-$ projekti töökausta.
Moodul moodulFunkid (moodulFunkid.py) sisaldab kursuse jooksul loodud funktsioonide definitsioone. Joonis 1 kujutab kahte moodulit mis asuvad samas arvuti failisüsteemi kaustas ehk kataloogis. Kursuse kodulehelt on võimalik alla laadida Joonisel 1 kujutatud projekti failid mis on salvestatud faili 1.zip.
| Joonis 1. Moodulid mis asuvad samas kataloogis ehk kaustas. |
NB! Seega, kui soovid teatud moodulis defineeritud objekte taaskasutada mingis muus moodulis paiguta mõlemad moodulid samasse töökausta ehk kataloogi.
2.2 Lausend import¶
Teise mooduli kasutamiseks, hetkel avatud moodulis, tuleb see importida kasutades lausendit import. Importida saame terve mooduli (import või konstruktsioon import/as või konstruktsioon from/import/*) või konktreetseid objekte kasutades konstruktsioone from/import, from/import/as. Kõik erinevad importimise viisid on loetletud siin:
import <moodul>
import <moodul1>, <moodule2>, <moodul3>
import <moodul> as <nimi> # Tavaliselt lühendame nime.
from <moodul> import <atribuut1>, <atribuut2>, <funktsioon1>, <klass1>
from <moodul> import <atribuut1> as <nimi>
from <moodul> import * # Impordib kõik, koodis mooduli nimele viitamine pole vajalik.
Kui imporditavat moodulit ei leita, siis tõstatakse erisus ImportError.
Märkus: Importimine teostatakse üldjuhul mooduli alguses enne kui kirjutatakse muu kood.
Näide: Avame ja uurime moodulit Loeng10_1 millega on kaasas moodul moodulFunkid (1.zip fail).
import moodulFunkid
print(dir(moodulFunkid)) # Mooduli sisu.
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'ascii_plot', 'astenda', 'cacheit', 'factorial', 'fibonacci', 'keskmine', 'kuup', 'loendi_keskmine', 'my_map', 'namefunc', 'pi', 'polunoom', 'recursive_factorial', 'recursive_fibonacci', 'ruut', 'ruutvorrand', 'ruutvorrand1', 'ruutvorrand2', 'solkija', 'taylor_exp', 'taylor_sin', 'tuletis']
Kindlale objektile viitamiseks kasutame punkti <moodul>.<objekt>:
print(moodulFunkid) # Mis andmetüübiga on tegu? Mis objekt?
print(moodulFunkid.ruutvorrand) # Viitan kindlale objektile.
<module 'moodulFunkid' from '/Users/dmitrikartofelev/Documents/WORK Teaching/YFX0500/Loeng 10/moodulFunkid.py'> <function ruutvorrand at 0x108c50900>
Moodulis defineeritud muutujatele ehk atribuudile viitamine:
moodulFunkid.pi # Atribuut, moodulis asuv muutuja.
3.141592653589793
Moodulis defineeritud funktsiooni kasutamine:
x1, x2 = moodulFunkid.ruutvorrand(1, 2, 3)
# ^ ^ ^ ^ ^
# moodul funktsioon argument
print('Ruutvõrrandi lahend x1 =', x1)
print('Ruutvõrrandi lahend x2 =', x2)
Ruutvõrrandi lahend x1 = (-0.9999999999999999+1.4142135623730951j) Ruutvõrrandi lahend x2 = (-1-1.4142135623730951j)
Keegi ei keela meil imporditud funktsioonile uut nime andmast:
rv = moodulFunkid.ruutvorrand # Uus nimi.
print('Nimetasin ümber', rv(-3, 5, 7))
Nimetasin ümber (-0.9067177514850918, 2.5733844181517584)
Tihti on kasulik mooduli nime lühendada. Impordime mooduli moodulFunkid uuesti:
import moodulFunkid as mF # Lühendan mooduli nime.
x1, x2 = mF.ruutvorrand(1, 2, 3) # Väljakutse uue nimega.
print('Ruutvõrrandi lahend x2 =', x2)
Ruutvõrrandi lahend x2 = (-1-1.4142135623730951j)
from moodulFunkid import ruutvorrand # Kindla funktsiooni import.
x1, x2 = ruutvorrand(-1, -2, 33) # Nüüd pole vaja viidata moodulile.
print('Ruutvõrrandi lahend x2 =', x2)
Ruutvõrrandi lahend x2 = 4.830951894845301
from moodulFunkid import ruutvorrand as rv # Lühendame kindla funktsiooni nime.
x1, x2 = rv(-11, -2, 3) # pole vaja viidata moodulile
print('Ruutvõrrandi lahend x2 =', x2)
Ruutvõrrandi lahend x2 = 0.4391774449859364
Kõikide objektide import:
from moodulFunkid import * # Impordib nimed kohalikku nimeruumi.
x1, x2 = ruutvorrand(-3, 2, 3) # Pole vaja viidata mooduli nimele.
print('Ruutvõrrandi lahend x2 =', x2)
print('Pi =', pi) # Pole vaja viidata mooduli nimele.
Ruutvõrrandi lahend x2 = 1.3874258867227933 Pi = 3.141592653589793
Märkus: Kui imporditav moodul sisaldab funktsiooni print väljakutset siis esmasel importimisel teostatakse printimine. Sama kehtib muude funktsiooni väljakutsete kohta.
2.3 Pakett¶
2.3.1 Mõiste¶
Pythoni pakett on failisüsteemi kataloogi puu, mille iga kataloog (kaust) sisaldab vähemalt ühte Pythoni moodulit nimega __init__ (__init__.py). Fail __init__.py on tühi või sisaldab suhtelisi viiteid.
- Pythoni paketi nimi on kataloogi (kausta) nimi.
- Pythoni paketi kasutus sarnaneb moodulil kasutusele.
Joonis 2 kujutab Pythoni paketi struktuuri ja faile.
Joonis 2. Pythoni paketti struktuur koos __init__.py failiga. |
2.3.2 Tühja faili __init__.py kasutamine¶
Kui __init__.py fail on tühi siis impordime paketti kasutades järgmist süntaksit. Nii nagu eespool moodulite puhul toetatakse ka siin erinevaid importimise viisi:
import <pakett>.<moodul>
import <pakett>.<moodul> as <nimi>
from <pakett>.<moodul> import <atribuut1>, <atribuut2>, <funktsioon1>, <klass1>
from <pakett>.<moodul> import <funktsioon1> as <nimi>
from <pakett>.<moodul> import * # Impordib kõik, mooduli nimele viitamine pole vajalik.
Alampaketi mooduli import:
import <pakett>.<alampakett>.<moodul>
2.3.3 Mittetühja faili __init__.py kasutamine¶
Kui fail __init__.py sisaldab suhtelisi viiteid kõikidele objektidele mida projektis on plaanitud kasudada. Viidete kasutamine lühendab importimise süntaksit. Tüüpiline __init__.py faili sisu:
from .<moodul1> import <funktsioon1>
from .<moodul2> import *
Punktide kasutus: . tähistab paketti, .. alampaketti ja ... alamalampaketti jne. Kui moodulis __init__ (__init__.py) on eelmainitud suhtelised viited toimub import järgmiselt:
import <pakett> # Juurdepääs kõikide moodulite kõikidele objektidele.
import <pakett> as <nimi>
from <pakett> import <funktsioon1 (moodul1)>, <atribuut1 (moodul2)> # Näiteks.
from <pakett> import <funktsioon2> as <nimi>
from <pakett> import *
Vajadus viidata kindlale kaustas asuvale moodulile pole enam vajalik. Relatiivsed viited lubavad paketil käituda sarnaselt moodulile. Imporditud moodulite ja pakketide sisu järgivaatamiseks kasutame endiselt funktsiooni dir.
2.3.4 Paketi kasutamise näited¶
Näited praktikumis või kodus uurimiseks: Avame ja uurime mooduleid Loeng10_2 ja Loeng10_3 ning nendega kaasaskäivat paketti nimega pakettFunkid:
- Failis 2.zip on salvestatud Pythoni projekt mis sisaldab paketti koos tühja
__init__.pyfailiga - Failis 3.zip on salvestatud Pythoni projekt mis sisaldab paketti koos mittetühja viidetega
__init__.pyfaili.
Praktikumi 10 ülesanded sisaldavad lisajuhiseid mis aitavad edukalt eelmainitud paketti kasutada.
2.4 Spetsiaalne muutuja __name__¶
2.4.1 Peaprotseduur ja konstruktsioon if __name__ == '__main__':¶
Oletame, et me töötame mitme mooduliga. Kuna Pythonis saab programmi käivitada meelevaldselt valitud moodulist (pole määratud ranget interpreteerimise alguspunkti) siis on tekkinud tava kirjutada moodulit ja selles olevat peaprotseduuri mida nimetatakse tavaliselt kasutades nime main järgmiselt:
from moodul_name import func1
def func2(): # Seda funktsiooni saad kasutada kolmandas moodulis.
pass
def main(): # Siin teed funktsioonidega midagi...
func1() # Kontrollid loogikat ja tegevuste järjekorda.
func2()
if __name__ == '__main__':
main()
Kasutatud if-tingimus tagab selle, et programmi peaprotseduur main käivitub ainult juhul kui interpreteerime algab sellest moodulist kus mainitud if-blokk asub. Eelöeldu töötab kuna moodulile kust alustatakse interpreteerimine omistatakse taustal spetsiaalsele muutujale __name__ väärtuseks '__main__' (andmetüübis sõne).
Peaprotseduur on protseduur millele pannakse tavaliselt nimeks main ning mis on kaitstud eelmises lõigus mainitus nimevalvuriga või nimehalduriga (if-plokk). Peaprotseduuri tööks on juhtida kogu programmi töövoogu ja kutsuda välja kõik teised kasutatavad protseduurid, funktsioonid, muutujad ja klassid olgu nad lokaalselt globaalselt defineeritud või imporditud mujalt moodulitest..
Imporditud mooduli puhul määratakse selle mooduliga seotud spetsiaalsele muutujale __name__ väärtuseks mooduli enda nimi sõne formaadis.
Näide: Spetsiaalse muutuja __name__ väärtuse järelevaatamiseks saame kasutada näiteks eelnevalt kasutatud moodulit moodulFunkid mis sisaldab protseduuri namefunc. Funktsiooni namefunc sisu on järgmine:
def namefunc():
'''Protseduur mis prindib mis teostab väljakutse
print('\nmoodulFunkid spetsiaalne nimi __name__ =', __name__)
'''
print('\nmoodulFunkid spetsiaalne nimi __name__ =', __name__)
import moodulFunkid
print(moodulFunkid.__name__) # Mooduli spetsiaalse muutuja __name__ järgivaatamine.
moodulFunkid.namefunc()
print('\nSelle mooduli spetsiaalne nimi __name__ =', __name__) # Interpreteerimine algab siit.
moodulFunkid moodulFunkid spetsiaalne nimi __name__ = moodulFunkid Selle mooduli spetsiaalne nimi __name__ = __main__
Küsimus: Mis juhtub kui me alustame interpreteerimist moodulist moodulFunkid?
2.5 Mooduli DocString ja mooduli dokumenteerimine¶
Vastavalt PEP 8-le (Style Guide for Python Code) peab ka mooduleid dokumenteerima. Kasuta PEP 257 (Docstring Conventions) soovitusi. Mooduli DocString kirjutatakse mooduli algusesse. Kasuta mitmerealist sõnet (multiline string) kujul:
"""Pealkiri
Optional plotz says to frobnicate the bizbaz first.
Sisu kirjuta siia. Eelmine rida on näide.
"""
Mooduli DocString'i järgivaatamiseks kasuta sama lähenemist mis muude objektide abiinfo ja dokumentatsiooni lugemisel:
import moodulFunkid
#help(moodulFunkid) # Vt. iseseisvalt, liiga pikk väljatrükk.
# Konsoolis töötab ka nii:
moodulFunkid?
Type: module String form: <module 'moodulFunkid' from '/Users/dmitrikartofelev/Documents/WORK Teaching/YFX0500/Loeng 10/moodulFunkid.py'> File: ~/Documents/WORK Teaching/YFX0500/Loeng 10/moodulFunkid.py Docstring: Moodul moodulFunkid Moodul sisaldab kursuse jooksul loodud funktsioone mis on loodud õpilaste poolt. Funktsiooni on kokku kogutud ja dokumenteeritud tudengite abiga. Viimati uuendatud: 2.11.2025.
Taustal on DocString'i sisu seotud spetsiaalse muutujaga __doc__, seega:
print(moodulFunkid.__doc__)
Moodul moodulFunkid Moodul sisaldab kursuse jooksul loodud funktsioone mis on loodud õpilaste poolt. Funktsiooni on kokku kogutud ja dokumenteeritud tudengite abiga. Viimati uuendatud: 2.11.2025.
2.6 Dünaamiline import¶
Teatavasti lokaliseerib def-plokk enda muutujad. LEGB reegel kehtib ka imporditud mooduli nimede puhul:
def my_pi():
import math
print("Lokaalne pi =", math.pi)
my_pi()
print("Globaalne pi =", math.pi) # LEGB reegel.
Lokaalne pi = 3.141592653589793
--------------------------------------------------------------------------- NameError Traceback (most recent call last) Cell In[13], line 6 3 print("Lokaalne pi =", math.pi) 5 my_pi() ----> 6 print("Globaalne pi =", math.pi) NameError: name 'math' is not defined
Kui sul on vaja juhtida importimise protsessi vasavalt mingile loogikale (tingimuslikult) siis saad kasutada nn. dünaamilist importimist. Selleks on loodud funktsioonid mis tagastavad mooduli objekti:
def dynamic_import(module_name):
return __import__(module_name)
my_math = dynamic_import("math")
print(my_math.sqrt(25))
5.0
Lisaks spetsiaalsele funktsioonile __import__, kehtib ka:
import importlib
def dynamic_import(module_name):
return importlib.import_module(module_name)
my_math = dynamic_import("math")
print(my_math.sqrt(25))
5.0
Kui soovid kindlat mooduli objekti importida:
def dynamic_import(module_name, func_name=None):
module = __import__(module_name)
return getattr(module, func_name) if func_name else module
sqrt_func = dynamic_import("math", "sqrt")
print(sqrt_func(25))
5.0
Allolevas tabelis võrreldakse staatilist importi kahe erinevat tüüpi dünaamilise impordiga:
| Meetod | return |
Soovitatud? | Märkus |
|---|---|---|---|
import module |
Ei | - | Lausend |
__import__(name) |
Ja | OK | Sisseehitaud funktsioon. |
importlib.import_module(name) |
Ja | Parim viis | Selgem, standard. |
3 Pythoni standardteek ja selle kasutamine¶
Lausendit import kasutame ka Pythoni standardteekide ja moodulite ning kolmandate osapoolte teekide ja moodulite importimiseks kohalikku nimeruumi.
Info Pythoni standardteekide kohta: https://docs.python.org/3/library/index.html
Kolmandate osapoolte teeke ja mooduleid peab enne kasutamist installeerima, vt. Lõik 5. Interpretaator teab kuhu on installeeritud moodulid salvestatud. Lausendi import kasutamine eelnevalt installeeritud mooduli importimine teostatakse automaatselt. Kasutaja ei pea mooduleid töökausta salvestama. Joonis 3 kujutab Pythoni programmi ja selle osasid.
| Joonis 3. Programmeerimine Pythonis. Pythoni programm ja selle osad. |
3.1 Valik mooduleid¶
Valik olulisemaid Pythoni standardteeke (pakettid) ja/või mooduleid:
string, re
datetime
collections
types
pprint
math
decimal
random, fractions
itertools
os.path
glob
shutil
pickle, shelve
zlib, zipfile, ...
csv
os
time
argparse
getpass
ctypes
threading
multiprocessing, subprocess
html, xml
urllib
sys
3.2 Importimise näiteid¶
Imporditud objekte kasutame vastavalt ja kooskõlas nende dokumentatsioonile ja andmetüübile.
2.2.1 Moodul math¶
Mooduli math kasutamise näiteid:
import math
print(dir(math))
['__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'cbrt', 'ceil', 'comb', 'copysign', 'cos', 'cosh', 'degrees', 'dist', 'e', 'erf', 'erfc', 'exp', 'exp2', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'isqrt', 'lcm', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'nextafter', 'perm', 'pi', 'pow', 'prod', 'radians', 'remainder', 'sin', 'sinh', 'sqrt', 'sumprod', 'tan', 'tanh', 'tau', 'trunc', 'ulp']
type(math)
module
print(math.pi)
print(math.e)
3.141592653589793 2.718281828459045
math.exp(1) == math.e
True
math.cos(0)
1.0
math.sin(2 * math.pi) # NB! Ujuvkomakoht, sin(2π) = 0.
-2.4492935982947064e-16
3.2.2 Moodul collections¶
Mooduli collections kasutamise näide:
from collections import Counter
lause = 'Juulius Tipikas on TalTech igavene tudeng.'
count = Counter(lause)
print(count)
print(count[' ']) # Käitub nagu sõnastik.
print(count['u'])
print(type(count))
Counter({' ': 5, 'u': 4, 'i': 4, 'e': 4, 'T': 3, 'a': 3, 'n': 3, 'l': 2, 's': 2, 'g': 2, 'J': 1, 'p': 1, 'k': 1, 'o': 1, 'c': 1, 'h': 1, 'v': 1, 't': 1, 'd': 1, '.': 1})
5
4
<class 'collections.Counter'>
nums = [1, 1, 1, 2, 3, 4, 5]
count = Counter(nums)
print(count)
print(count[1]) # Käitub nagu sõnastik.
print(count[2])
Counter({1: 3, 2: 1, 3: 1, 4: 1, 5: 1})
3
1
3.2.3 Moodul random¶
Mooduli random kasutamise näide:
from random import choice
fruits = ['Juulius', 'Juulia', 'Anu', 'Kalle']
print(choice(fruits)) # Juhuslik valik loendist.
choice?
Juulius
Signature: choice(seq) Docstring: Choose a random element from a non-empty sequence. File: /opt/anaconda3/lib/python3.12/random.py Type: method
from random import randint
print(randint(1, 100)) # Juhuslik arv.
randint?
14
Signature: randint(a, b) Docstring: Return random integer in range [a, b], including both end points. File: /opt/anaconda3/lib/python3.12/random.py Type: method
3.2.4 Standarteegi pprint¶
Mooduli pprint kasutamise näide:
from pprint import pprint
data = {
"name": "Juulius",
"weapons": ["light gun", "mech cannons", "fusion missiles"],
"stats": {
"hp": 600,
"armor": 200,
"speed": 5.5
},
"abilities": [
{"name": "Boosters", "cooldown": 5},
{"name": "Defense Matrix", "cooldown": 2},
{"name": "Self-Destruct", "cooldown": 0}
]
}
print("Using print():")
print(data)
print("\nUsing pprint():")
pprint(data)
Using print():
{'name': 'Juulius', 'weapons': ['light gun', 'mech cannons', 'fusion missiles'], 'stats': {'hp': 600, 'armor': 200, 'speed': 5.5}, 'abilities': [{'name': 'Boosters', 'cooldown': 5}, {'name': 'Defense Matrix', 'cooldown': 2}, {'name': 'Self-Destruct', 'cooldown': 0}]}
Using pprint():
{'abilities': [{'cooldown': 5, 'name': 'Boosters'},
{'cooldown': 2, 'name': 'Defense Matrix'},
{'cooldown': 0, 'name': 'Self-Destruct'}],
'name': 'Juulius',
'stats': {'armor': 200, 'hp': 600, 'speed': 5.5},
'weapons': ['light gun', 'mech cannons', 'fusion missiles']}
3.2.4.1 Moodul sympy.pprint¶
Mooduli sympy.pprint kasutamise näide:
from sympy import symbols, Integral, sin, pprint
x = symbols('x') # Defineerime sümboli.
# Defineerime integraali (ei võta integraali).
expr = Integral((x**2/5) * sin(x), x)
pprint(expr)
⌠ ⎮ 2 ⎮ x ⋅sin(x) ⎮ ───────── dx ⎮ 5 ⌡
3.2.5 Moodul this¶
Pythoni standardteek sisaldab järgmist moodulit:
import this
The Zen of Python, by Tim Peters Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Sparse is better than dense. Readability counts. Special cases aren't special enough to break the rules. Although practicality beats purity. Errors should never pass silently. Unless explicitly silenced. In the face of ambiguity, refuse the temptation to guess. There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch. Now is better than never. Although never is often better than *right* now. If the implementation is hard to explain, it's a bad idea. If the implementation is easy to explain, it may be a good idea. Namespaces are one honking great idea -- let's do more of those!
import this, inspect
print(inspect.getsource(this))
s = """Gur Mra bs Clguba, ol Gvz Crgref
Ornhgvshy vf orggre guna htyl.
Rkcyvpvg vf orggre guna vzcyvpvg.
Fvzcyr vf orggre guna pbzcyrk.
Pbzcyrk vf orggre guna pbzcyvpngrq.
Syng vf orggre guna arfgrq.
Fcnefr vf orggre guna qrafr.
Ernqnovyvgl pbhagf.
Fcrpvny pnfrf nera'g fcrpvny rabhtu gb oernx gur ehyrf.
Nygubhtu cenpgvpnyvgl orngf chevgl.
Reebef fubhyq arire cnff fvyragyl.
Hayrff rkcyvpvgyl fvyraprq.
Va gur snpr bs nzovthvgl, ershfr gur grzcgngvba gb thrff.
Gurer fubhyq or bar-- naq cersrenoyl bayl bar --boivbhf jnl gb qb vg.
Nygubhtu gung jnl znl abg or boivbhf ng svefg hayrff lbh'er Qhgpu.
Abj vf orggre guna arire.
Nygubhtu arire vf bsgra orggre guna *evtug* abj.
Vs gur vzcyrzragngvba vf uneq gb rkcynva, vg'f n onq vqrn.
Vs gur vzcyrzragngvba vf rnfl gb rkcynva, vg znl or n tbbq vqrn.
Anzrfcnprf ner bar ubaxvat terng vqrn -- yrg'f qb zber bs gubfr!"""
d = {}
for c in (65, 97):
for i in range(26):
d[chr(i+c)] = chr((i+13) % 26 + c)
print("".join([d.get(c, c) for c in s]))
4 Kolmandate osapoolte teegid ja moodulid¶
Avalikuks kasutamiseks loodud moodulid on indekseeritud ja vabalt kautatamiseks allalaetavad. Veebisaidilt "Python Package Index" (PyPI) https://pypi.org/ leiab eelmainitud tarkvara. Lisaks sisaldab see sait infot ja juhiseid ka enda kirjutatud tarkvara avalikustamise ja jagamise kohta.
Peale kolmandate osapoolte teekide või moodulite installeerimist (vt. Lõik 5) saab neid importida kasutades lausendit import.
4.1 Valik teadusarvutustes kasutatud teeke ja mooduleid¶
Tulevastes loengutes räägime allolevatest teekidest põhjalikumalt.
| Joonis 4. Loetletud teekide ja projektide logod. Seisuga 2023. |
Valik olulisemaid teeke (Anacondaga vaikimisi kaasas) millede logod on kujutatud Joonisel 4:
- NumPy — andmete esitus massiividena ja teadusarvutuste algoritmid, https://numpy.org
- SciPy — Muud teadusarvutuste algoritmid, https://www.scipy.org
- matplotlib — andmete analüüs ja visualiseerimine, https://matplotlib.org
- pandas — andmete salvestus ja analüüs, https://pandas.pydata.org
- IPython — interaktiivne andmete analüüs, https://ipython.org
- SymPy — sümbolarvutus, computer algebra system (CAS) või symbolic algebra system (SAS), https://www.sympy.org/en/index.html
4.1.1 Näide teegi numpy import¶
import numpy as np
type(np)
module
Andmemasiivi defineerimine:
x = np.array([1, 2, 3])
type(x)
numpy.ndarray
print(np.pi)
print(np.e)
3.141592653589793 2.718281828459045
np.exp(1) == np.e
True
np.cos(0)
1.0
np.sin(2 * np.pi) # NB! Ujuvkomakoha määramatus, sin(2π) = 0.
-2.4492935982947064e-16
5 Pythoni distributsiooni haldamine¶
5.1 Moodulite installeerimine ja eemaldamine kasutades pip'i¶
Eelmises lõigus mainitud tarkvara allalaadimiseks ja installeerimiseks kasutame spetsiaalselt selleks loodud Pythoni installatsiooniga kaasas olevat standardteegi tarkvara.
Kui kasutad Anacondast erinevat Pythoni distributsiooni installatsiooni siis kasuta konsoolis käsku pip.
Konsooli käsud:
PyPI tavalises konsoolis
pippip -h, abimaterjal (help)pip list, instaleeritud teekide ja moodulite nimistu ja versioonidpip install <nimi>, instaleeri uus teek/moodulpip uninstall <nimi>eemalda instaleeritud teek/moodul
5.2 Moodulite installeerimine ja eemaldamine kasutades conda't¶
Anaconda konsoolis
condaconda -h, abimaterjal (help)conda list, instaleeritud teekide ja moodulite nimistu ja versioonidconda install <nimi>, instaleeri uus teek/moodulconda uninstall <nimi>võiconda remove <nimi>, eemalda instaleeritud teek/moodul
Anaconda konsoolis töötavad ka pip'i käsud. Kui arvutisse on installeeritud Anaconda distributsioon siis on soovitatav kasutada ainult conda käske.
6 Koodi modulaarsus¶
Nii nagu suuremat probleemi jagame erinevate mooduli failide vahele on soovitatav ka mooduli piires probleem jagada väiksemateks alamprobleemideks. Alamprotseduurid võiksid olla muust koodist sõltumatud.
Allolevate koodinäidete taga on programm mis kodeerib "poomise" mängu inglisekeelse versiooni. Mängus "poomine" püüab kasjutaja talle teadmata sõna täht tähe haaval ära arvata. Programmis valib kasutaja mängu keerukuse ning üritab ennustada sõna, mis on valitud juhuslikult ette antud nimekirjast.
6.1 Halb modulaarsuse näide ja programm "poomine":¶
import random as r
words_easy = ["table", "star", "root", "flat", "turtle", "fish", "goat"]
words_hard = ["dragonborn", "monosaccharide", "disposable", "environment"]
difficulty = input("Please select difficulty('h' for 'hard' and 'e' for 'easy'): ")
if difficulty == 'h':
words = words_hard
elif difficulty == 'e':
words = words_easy
else:
raise ValueError("Not allowed input.")
word = r.choice(words)
guesses = len(word)
guess_word = ["-"] * len(word)
while True:
print(f"\nGuesses left: {guesses}")
print(f"The word is: {''.join(guess_word)}")
char = input("Please enter single character: ")
if char in word:
for i in range(len(word)):
guess_word[i] = char if word[i] == char else guess_word[i]
else:
print(f"The character {char} is not in the word!")
guesses -= 1
if "".join(guess_word) == word:
print("\nYou won!")
print(f"The word is: {word}")
break
if guesses == 0:
print("\nYou lost!")
print(f"The word was {word}")
break
6.2 Hea modulaarsuse näide ja programm "poomine"¶
import random as r
def select_difficulty(words_hard, words_easy):
difficulty = input("Please select difficulty ('h' for 'hard' and 'e' for 'easy'): ")
if difficulty == 'h':
words = words_hard
elif difficulty == 'e':
words = words_easy
else:
raise ValueError("Not allowed input.")
return words
def update_word(word, guess_word, char):
for i in range(len(word)):
if word[i] == char:
guess_word[i] = char
def track_game_state(word, guess_word, guesses):
if "".join(guess_word) == word:
print("\nYou won!")
print(f"The word is: '{word}'")
return True
if guesses == 0:
print("\nYou lost!")
print(f"The word was '{word}'")
return True
return False
def game(words_hard, words_easy):
words = select_difficulty(words_hard, words_easy)
word = r.choice(words)
guesses = len(word)
guess_word = ["-"] * len(word)
finished = False
while not finished:
print(f"\nGuesses left: {guesses}")
print(f"The word is: {''.join(guess_word)}")
char = input("Please enter single character: ")
if char not in word:
print(f"The character '{char}' is not in the word!")
guesses -= 1
else:
update_word(word, guess_word, char)
finished = track_game_state(word, guess_word, guesses)
def main():
easy = [
"table", "star", "root", "flat",
"turtle", "fish", "goat"
]
hard = [
"dragonborn", "monosaccharide",
"disposable", "environment"
]
game(words_hard=hard, words_easy=easy)
if __name__ == '__main__':
main()