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().

>>> 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 importimise viisist.

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

import random

dice_roll = random.randint(1, 6)
print(dice_roll)

Konkreetse definitsiooni importimine. Toob otse nimeruumi. Tegemist võib olla ka konstandiga, klassiga.

from string import ascii_lowercase, digits

print(ascii_lowercase)  # -> abcdefghijklmnopqrstuvwxyz
print(digits)  # -> 0123456789

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 alternatiivse nime.

import random as rnd

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

Moodulist võib mõelda ka kui objektist, mis defineeritakse.

import collections

print(type(collections))  # -> <class 'module'>

Mooduli käivitamine skriptina

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

Enda loodud moodul fibo.py:

"""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 ei pane. Olgu meil moodul dice.py.

"""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 ilusti. Tulemus prinditi konsooli.

Nüüd me soovime 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 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 print käsud. Just selleks ongi olemas __main__.

Uuendades moodulit dice.py.

"""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()}")

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

Stiil importimisel

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

Impordid võiks olla eraldi real, mitte komaga eraldatud, v.a juhul kui tehakse täpne import.

import math
from random import randint, shuffle, choice

Importidel peaks 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