Moodul

Moodulid on Pythonis .py failid, mis sisaldavad mingit hulka definitsioone.

Pythoni interpretaatorist lahkudes kaovad kõik loodud funktsioonid ja muutujad. Seega tasub suurema programmi loomiseks luua fail ja see hiljem käivitada. Seda nimetatakse Pythoni skripti loomiseks. Liigselt suured programmid tasub jagada väiksemateks mooduliteks, mida on lihtsam hallata.

Moodulite importimine toimub võtmesõnaga import. Reeglina imporditakse vajalikud moodulid kohe programmi alguses.

Pythoniga on kaasas hulk standardmooduleid. Mõned populaarsemad:

  • math - matemaatilised operatsioonid

  • random - juhuslikkus

  • os - opsüsteemi spetsiifiline funktsionaalsus

  • sys - info enda süsteemi kohta

  • collections - konteinerid

  • time - operatsioonid ajaga

  • re - regulaaravaldised

  • datetime - kuupäevad, kellaajad

  • csv - CSV failide lugemine/kirjutamine

  • string - operatsioonid sõnedega, kasulikud konstandid

  • itertools - efektiivsed itereerimisega seotud funktsioonid

Mooduli sisu saab ka näha funktsiooniga dir(). Näitena juhuslikkuse mooduli sisu:

>>> import random
>>> dir(random)
['BPF', 'LOG4', 'NV_MAGICCONST', 'RECIP_BPF', 'Random', 'SG_MAGICCONST', 'SystemRandom',
'TWOPI', '_BuiltinMethodType', '_MethodType', '_Sequence', '_Set', '__all__', '__builtins__',
'__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__',
'_acos', '_bisect', '_ceil', '_cos', '_e', '_exp', '_inst', '_itertools', '_log', '_pi',
'_random', '_sha512', '_sin', '_sqrt', '_test', '_test_generator', '_urandom', '_warn',
'betavariate', 'choice', 'choices', 'expovariate', 'gammavariate', 'gauss', 'getrandbits',
'getstate', 'lognormvariate', 'normalvariate', 'paretovariate', 'randint', 'random', 'randrange',
'sample', 'seed', 'setstate', 'shuffle', 'triangular', 'uniform', 'vonmisesvariate','weibullvariate']

Kogu Pythoni standardteek: https://docs.python.org/3/library/index.html

Mooduli kasutamine

Moodulis oleva funktsiooni kasutamine sõltub selle importimise viisist.

  1. Üldine importimine. Definitsiooni kasutamiseks peab kasutama mooduli nime ja punkti.

import random

dice_roll = random.randint(1, 6)
print(dice_roll)
  1. Konkreetse definitsiooni importimine. Selline viis toob funktsiooni otse nimeruumi. Tegemist võib olla ka konstandiga, klassiga.

from string import ascii_lowercase, digits

print(ascii_lowercase)  # -> abcdefghijklmnopqrstuvwxyz
print(digits)  # -> 0123456789
  1. Kõige importimine ja otse nimeruumi toomine.

from itertools import *

print(list(combinations("abc", 2)))  # -> [('a', 'b'), ('a', 'c'), ('b', 'c')]
print(list(permutations("123")))  # -> all the permutations

Imporditavale moodulile saab anda ka alternatiivse nime. Näitena juhuslikkuse mooduli importimine soovitud nimega:

import random as rnd

print(rnd.choice((True, False)))

Mooduli käivitamine skriptina

PyCharmis on moodulite töölepanek lihtne, tuleb lihtsalt vajutada nuppu Run. Terminalist tuleb skripti käivitamiseks kirjutada käsureale python faili_nimi.py <argumendid>.

Näitena loodud moodul fibo.py Dibonacci numbrite arvutamiseks:

"""Fibonacci numbers module."""
import sys


def fib(n):
    """Calculate the n-th fibonacci number."""

    if n == 0:
        return 0
    if n == 1:
        return 1
    fibo_prev, fibo = 0, 1
    for _ in range(2, n + 1):
        fibo_prev, fibo = fibo, fibo_prev + fibo
    return fibo


if __name__ == '__main__':
    print(fib(int(sys.argv[1])))

Olles käsureal samas kaustas, kus asub moodul fibo.py, saame käivitada skripti nt argumendiga 15.

C:\>python fibo.py 15
610

if __name__ == "__main__":

Mooduli importimisel käivitatakse seal olev kood. Kui me tahame midagi käima panna skriptina, siis tasub mooduli lõppu panna järgnev kood:

if __name__ == "__main__":
    pass

__name__ on spetsiaalne muutuja, mis määratakse koodile käima panemisel. Kui skript pannakse otse tööle, siis saab muutuja __name__ väärtuse "__main__". Importimisel saab muutuja väärtuseks mooduli nime.

Vaatame, mis juhtub, kui seda koodijuppi näiteks ei kasuta. Olgu meil olemas moodul dice.py, mis veeretab täringuid:

"""Dice rolling module."""

from random import randint


def dice_roll():
    return randint(1, 6)


def roll_two_dices():
    return dice_roll() + dice_roll()


print("Rolling a dice...")
print(f"The value is: {dice_roll()}")

Paneme selle programmi käsurealt tööle. Kuna argumente pole vaja edastada, siis pole sys moodulit vaja sisse tuua.

C:\>python dice.py
Rolling a dice...
The value is: 4

Tundub, et kõik töötab nii nagu vaja ja tulemus prinditi konsooli.

Nüüd aga soovime me simuleerida täringu viskeid suuremas koguses. Loome mooduli simulation.py:

"""A dice simulation module."""

import sys
from pprint import pprint

from dice import roll_two_dices


def simulate_rolls(n):
    """Print the count of each two dice roll
    value after n rolls."""
    d = {}
    for _ in range(n):
        v = roll_two_dices()
        d[v] = d.get(v, 0) + 1
    print(f"Simulating {n} rolls...")
    pprint(d)


simulate_rolls(int(sys.argv[1]))

Siin anname käsurealt tööle pannes juurde ka ühe argumendi. Käivitame terminalist skripti andes selle argumendiks 1000.

C:\>python simulation.py 1000
Rolling a dice...
The value is: 2
Simulating 1000 rolls...
{2: 24,
 3: 59,
 4: 80,
 5: 110,
 6: 139,
 7: 150,
 8: 138,
 9: 111,
 10: 83,
 11: 70,
 12: 36}

Mis nüüd juhtus? Käivitusid mooduli dice.py print käsud. Mooduli importimisel pannakse kogu kood tööle. Tahame, et mõlemat moodulit saaks skriptina käivitada, aga samas saaks ka importida ilma, et käivituks printimise käsud. Just selleks ongi olemas __main__.

Uuendades moodulit dice.py, käivituvad print käsud ainult juhul, kuid dice.py käivitatakse otse skriptina. Importimisel need enam tööle ei lähe.

"""Dice rolling module."""

from random import randint


def dice_roll():
    return randint(1, 6)


def roll_two_dices():
    return dice_roll() + dice_roll()


if __name__ == '__main__':
    print("Rolling a dice...")
    print(f"The value is: {dice_roll()}")

Stiil importimisel

Impordid peaksid alati asuma faili alguses, kohe peale mooduli docstringi. Vältima peaks kõige importimist: from <module> import *, sest see reostab liigselt nimeruumi ja võib koodi lugejaid segadusse ajada.

Import laused võiksid olla eraldi ridadel, mitte komaga eraldatud, v.a juhul kui tehakse konkreetne importimine.

import math
from random import randint, shuffle, choice

Import laused peaksid olema grupeeritud järgnevalt:

  1. Standardmoodulid

  2. Kolmandate poolte moodulid

  3. Kohalikud moodulid

import math
from random import randint

import numpy as np
import matplotlib.pyplot as plt

from EX01A import hello

Lisaks

Pythoni ametlik dokumentatsioon: https://docs.python.org/3/tutorial/modules.html

Stiilinõuded moodulite importimisel: https://www.python.org/dev/peps/pep-0008/#imports