Модули. Пакеты

Цель: научиться создавать собственные модули и пакеты, и затем использовать их с помощью инструментов импорта.

Примеры

Пример № 1

Создадим модуль algebra, который будет содержать две функции:

  • progress(a1, d, n) - возвращает список, который содержит элементы арифметической прогрессии; a1 - первый член прогрессии, d - разность прогрессии, n - количество элементов в списке.
  • func_table(f, x1, xn, step) - выводит на экран таблицу значений функции f, для x от x1 до xn с шагом step.

Создайте новый файл и сохраните его на рабочем диске под именем algebra.py:

algebra.py
def progress(a1, d, n):
    prog = []
    for i in range(1, n + 1):
        prog.append(a1 + d * (i - 1))
    return prog

def func_table(f, x1, xn, step):
    x = x1
    while x <= xn:
        y = f(x)
        print(f"x: {x:4.2f} y: {y:4.2f}")
        x += step

# тестируем модуль, если он не был импортирован 
if __name__ == "__main__":
    print(progress(1, 3, 10))
    def sqr(x):
        return x * x
    func_table(sqr, 0, 5, 0.2)

Пример:

[1, 4, 7, 10, 13, 16, 19, 22, 25, 28]
x: 0.00 y: 0.00
x: 0.50 y: 0.25
x: 1.00 y: 1.00
x: 1.50 y: 2.25
x: 2.00 y: 4.00
x: 2.50 y: 6.25
x: 3.00 y: 9.00
x: 3.50 y: 12.25
x: 4.00 y: 16.00
x: 4.50 y: 20.25

Создайте новый файл с именем pr1_main.py. Убедитесь, что он располагается в одной папке с созданным ранее модулем.

Импортируем модуль algebra для использования описанных в нём функций:

pr1_main.py
import algebra

print("Арифметическая прогрессия")
a1 = int(input("Первый член прогрессии: "))
d = int(input("Разность прогрессии: "))
n = int(input("Количество чисел в прогрессии: "))

# вызываем функцию из модуля
print(algebra.progress(a1, d, n))

def line(x):
    return 2 * x + 3

print("Табулированные функции 2x+3:")
# вызываем процедуру из модуля
algebra.func_table(line, -3, 3, 0.5)

Пример:

Арифметическая прогрессия
Первый член прогрессии: 3
Разность прогрессии: 2
Количество чисел в прогрессии: 5
[3, 5, 7, 9, 11]
Табулированные функции 2x+3:
x: -3.00 y: -3.00
x: -2.50 y: -2.00
x: -2.00 y: -1.00
x: -1.50 y: 0.00
x: -1.00 y: 1.00
x: -0.50 y: 2.00
x: 0.00 y: 3.00
x: 0.50 y: 4.00
x: 1.00 y: 5.00
x: 1.50 y: 6.00
x: 2.00 y: 7.00
x: 2.50 y: 8.00

Пример № 2

Создадим модуль geometr, который будет содержать описание класса Cone (Конус).

Класс будет содержать следующие поля:

  • l - образующая конуса
  • r - радиус основания конуса

Класс будет содержать следующие методы:

  • getSideSqr() - возвращает площадь боковой поверхности конуса
  • getFullSqr() - возвращает полную площадь поверхности конуса
  • getVolume() - вычисляет объём конуса

Площадь боковой поверхности вычисляется по формуле:

\[ S=\frac{1}{2}\pi rl \]

Полная площадь поверхности:

\[ S=\pi r(r + l) \]

Объём конуса:

\[ V=\frac{1}{3}\pi r^2H \]

где H - высота конуса.

Создайте новый файл и сохраните его под именем geometr.py:

geometr.py
from math import pi, sqrt

class Cone:
    def __init__(self, l, r):
        self.l = l
        self.r = r

    def getSideSqr(self):
        return 1/2 * pi * self.r * self.l

    def getFullSqr(self):
        return pi * self.r * (self.r + self.l)

    def getVolume(self):
        H = sqrt(self.l ** 2 - self.r ** 2)
        return 1/3 * pi * self.r ** 2 * H

Откройте файл pr1_main.py и добавьте к нему следующие строки кода, чтобы импортировать класс и проверить его работу:

pr1_main.py
from geometr import Cone

c1 = Cone(10, 3)
print("Боковая площадь:", c1.getSideSqr())
print("Полная площадь:", c1.getFullSqr())
print("Объём:", c1.getVolume())

Пример:

Боковая площадь: 47.12388980384689
Полная площадь: 122.52211349000193
Объём: 89.9066516142837

Пример № 3

На основе разработанных модулей создадим пакет mathhelp.

Создайте папку с именем mathhelp. Переместите в эту папку файлы algebra.py и geometr.py. Внутри папки создайте пустой файл с именем __init__.py. С его помощью интерпретатор поймёт, что данную папку можно считать пакетом.

Откройте основной файл pr1_main.py. Исправьте его таким образом, чтобы класс и функции импортировались из созданного пакета:

pr1_main.py
# импортируем функции и классы из пакета mathhelp
from mathhelp.algebra import progress, func_table
from mathhelp.geometr import Cone

print("Арифметическая прогрессия")
a1 = int(input("Первый член прогрессии: "))
d = int(input("Разность прогрессии: "))
n = int(input("Количество чисел в прогрессии: "))

print(progress(a1, d, n)) # исправлен вызов функции

def line(x):
    return 2 * x + 3

print("Табулированные функции 2x+3:")
func_table(line, -3, 3, 0.5) # исправлен вызов процедуры

c1 = Cone(10, 3)
print("Боковая площадь:", c1.getSideSqr())
print("Полная площадь:", c1.getFullSqr())
print("Объём:", c1.getVolume())

Проверьте работу исправленной программы.

Задания для самостоятельной работы

Задание № 1

Создайте модуль resistors, который содержит следующие функции:

  • parallel(r1, r2) - вычисляет общее сопротивление двух резисторов, соединённых параллельно
  • consec([r1, r2, r3, ...]) - вычисляет общее сопротивление резисторов, соединённых последовательно. В качестве параметра функция принимает список чисел.

При параллельном соединении двух резисторов с сопротивлением \(r_1\) и \(r_2\) общее сопротивление вычисляется по формуле:

\[ R_{пар}=\frac{r_1\cdot r_2}{r_1 + r_2} \]

При последовательном соединении резисторов, общее сопротивление равно сумме отдельных сопротивлений:

\[ R_{посл}=r_1 + r_2 + r_3 + ... \]

Шаблон программы:

resistors.py
# описание функции parallel(r1, r2)

# описание функции consec(lst)

# тестируем модуль, если он не был импортирован 
if __name__ == "__main__":
    print(parallel(300, 400))
    r_list = [420, 300, 1000]
    print(consec(r_list))

Создайте файл с именем sam1_main.py и сохраните его в той же папке, что и модуль resistors.

Используя модуль resistors, вычислите общее сопротивление двух проводников, соединённых параллельно. Сопротивления r1 и r2 вводятся с клавиатуры.

Пример:

Параллельное соединение
R1: 200
R2: 500
Общее сопротивление: 142.86

Задание № 2

Создайте модуль datatypes, который будет содержать класс Queue, моделирующий очередь.

Тип данных очередь работает по принципу “Первый вошёл - первый вышел”:

Очередь должна обладать следующими возможностями:

  • добавление элемента в очередь - элемент становится последним в очереди
  • выход из очереди - элемент, стоявший в очереди первым, удаляется из неё и возвращается в основную программу
  • проверка, является ли очередь пустой
  • получение количества элементов в очереди

Очередь можно реализовать с помощью переменной-списка и её методов (append, insert, pop).

Класс Queue должен содержать следующее поле:

  • items - список, который хранит элементы очереди; по умолчанию список пустой

Класс Queue должен содержать следующие методы:

  • __init__() - конструктор; присваивает полю items пустой список

  • add(item) - добавляет элемент item в конец очереди

  • remove() - возвращает элемент, который располагается в очереди первым и удаляет его из очереди

  • isEmpty() - возвращает True, если очередь пуста, иначе возвращает False

  • size() - возвращает количество элементов в очереди

Создайте файл datatypes.py и опишите в нём класс Queue. В представленном шаблоне замените комментарии на необходимый код:

datatypes.py
class Queue:
    def __init__(self):
        self.items = []

    def add(self, item):
        # вставляем элемент item в начало списка items (на позицию 0)

    def remove(self):
        # удаляем последний элемент списка items и возвращаем его

    def isEmpty(self):
        # возвращаем True, если items пуст, иначе - False

    def size(self):
        # возвращаем количество элементов в списке items

# тестируем модуль, если он не был импортирован 
if __name__ == "__main__":
    q = Queue()
    print("Очередь пуста?", q.isEmpty())
    q.add("Иван")
    print("Иван встал в очередь")
    q.add("Пётр")
    print("Пётр встал в очередь")
    print("Размер очереди:", q.size())
    print("Первым из очереди вышел", q.remove())
    print("Следующим из очереди вышел", q.remove())
    print("Размер очереди:", q.size())

Пример:

Очередь пуста? True
Иван встал в очередь
Пётр встал в очередь
Размер очереди: 2
Первым из очереди вышел Иван
Следующим из очереди вышел Пётр
Размер очереди: 0

Создайте файл с именем sam2_main.py и сохраните его в той же папке, что и модуль datatypes.

Смоделируем очередь печати принтера с помощью созданного вами класса Queue.

Замените комментарии в коде, импортом класса Queue из модуля datatypes. Затем создайте объект данного класса и сохраните его в переменной print_q. После этого добавьте минимум 3 строки в очередь:

sam2_main.py
# импортируйте класс Queue из модуля datatypes

print_q = # присвойте объект класса Queue

# добавьте минимум три строки в очередь print_q

print("Документов в очереди печати:", print_q.size())
while not print_q.isEmpty():
    print("Печатаем", print_q.remove())

print("Документов в очереди печати:", print_q.size())

Пример:

Документов в очереди печати: 3
Печатаем Курсовая.doc
Печатаем Объявление.jpg
Печатаем Отчёт.docx
Документов в очереди печати: 0