Python: Пакеты
По мере роста программы увеличивается не только количество строк кода, но и количество модулей. В небольших проектах десятки файлов еще можно держать в одной директории, но в реальных приложениях файлов могут быть сотни и тысячи.
Чтобы организовывать модули в более крупные логические группы, в Python используют пакеты. Пакет представляет собой директорию с Python-файлами.
Например, структура проекта может выглядеть так:
project/
├── main.py
├── payments/
│ ├── stripe.py
│ └── paypal.py
└── users/
├── auth.py
└── profile.pyВ этом примере payments и users являются пакетами, а stripe.py, paypal.py, auth.py и profile.py — модулями.
Пакеты помогают группировать код по задачам и упрощают навигацию по проекту. Вместо сотен файлов в одной директории код разделяется на отдельные области ответственности.
Импорт из пакета
К модулям внутри пакета обращаются через точку:
import payments.stripeПосле импорта можно использовать содержимое модуля:
import payments.stripe
payments.stripe.create_payment()Точка показывает путь внутри пакета. Python последовательно переходит от пакета к модулю.
Импорт конкретного модуля
Часто импортируют не весь путь, а конкретный модуль:
from payments import stripe
stripe.create_payment()Такой способ сокращает запись и делает код компактнее.
Вложенные пакеты
Пакеты могут содержать другие пакеты:
project/
└── app/
└── payments/
├── stripe/
│ ├── client.py
│ └── api.py
└── paypal.pyВ этом случае путь к модулю становится длиннее:
from app.payments.stripe import clientТакая структура часто встречается в больших проектах. Она помогает разделять код на независимые части.
Пакеты и пространства имен
Пакеты создают дополнительный уровень пространства имен. Благодаря этому разные части программы могут содержать модули с одинаковыми именами.
Например:
project/
├── admin/
│ └── config.py
└── user/
└── config.pyЗдесь существуют два разных модуля config.py.
Python различает их по полному пути:
import admin.config
import user.configБез пакетов такие имена конфликтовали бы между собой.
Файл init.py
Раньше для создания пакета внутри директории обязательно размещали файл __init__.py:
payments/
├── __init__.py
├── stripe.py
└── paypal.pyЭтот файл сообщал Python, что директорию нужно воспринимать как пакет.
В современных версиях Python пакеты могут работать и без __init__.py. Тем не менее этот файл до сих пор часто используется. Обычно в нем размещают общий код и настройки пакета.
Задание
Реализуйте функцию generate_pin(). Она возвращает случайный четырёхзначный PIN-код в виде строки.
Каждый разряд PIN-кода — независимое случайное целое число от 0 до 9.
print(generate_pin()) # => например, "4823" или "0571"
print(generate_pin()) # => например, "1942" или "0037"Укажите аннотацию типа возвращаемого значения.
Подсказка
Сгенерируйте каждую из четырёх цифр через random.randint(0, 9) и соберите строку через f-строку.
Python: Пакеты
По мере роста программы увеличивается не только количество строк кода, но и количество модулей. В небольших проектах десятки файлов еще можно держать в одной директории, но в реальных приложениях файлов могут быть сотни и тысячи.
Чтобы организовывать модули в более крупные логические группы, в Python используют пакеты. Пакет представляет собой директорию с Python-файлами.
Например, структура проекта может выглядеть так:
project/
├── main.py
├── payments/
│ ├── stripe.py
│ └── paypal.py
└── users/
├── auth.py
└── profile.pyВ этом примере payments и users являются пакетами, а stripe.py, paypal.py, auth.py и profile.py — модулями.
Пакеты помогают группировать код по задачам и упрощают навигацию по проекту. Вместо сотен файлов в одной директории код разделяется на отдельные области ответственности.
Импорт из пакета
К модулям внутри пакета обращаются через точку:
import payments.stripeПосле импорта можно использовать содержимое модуля:
import payments.stripe
payments.stripe.create_payment()Точка показывает путь внутри пакета. Python последовательно переходит от пакета к модулю.
Импорт конкретного модуля
Часто импортируют не весь путь, а конкретный модуль:
from payments import stripe
stripe.create_payment()Такой способ сокращает запись и делает код компактнее.
Вложенные пакеты
Пакеты могут содержать другие пакеты:
project/
└── app/
└── payments/
├── stripe/
│ ├── client.py
│ └── api.py
└── paypal.pyВ этом случае путь к модулю становится длиннее:
from app.payments.stripe import clientТакая структура часто встречается в больших проектах. Она помогает разделять код на независимые части.
Пакеты и пространства имен
Пакеты создают дополнительный уровень пространства имен. Благодаря этому разные части программы могут содержать модули с одинаковыми именами.
Например:
project/
├── admin/
│ └── config.py
└── user/
└── config.pyЗдесь существуют два разных модуля config.py.
Python различает их по полному пути:
import admin.config
import user.configБез пакетов такие имена конфликтовали бы между собой.
Файл init.py
Раньше для создания пакета внутри директории обязательно размещали файл __init__.py:
payments/
├── __init__.py
├── stripe.py
└── paypal.pyЭтот файл сообщал Python, что директорию нужно воспринимать как пакет.
В современных версиях Python пакеты могут работать и без __init__.py. Тем не менее этот файл до сих пор часто используется. Обычно в нем размещают общий код и настройки пакета.
Задание
Реализуйте функцию generate_pin(). Она возвращает случайный четырёхзначный PIN-код в виде строки.
Каждый разряд PIN-кода — независимое случайное целое число от 0 до 9.
print(generate_pin()) # => например, "4823" или "0571"
print(generate_pin()) # => например, "1942" или "0037"Укажите аннотацию типа возвращаемого значения.
Подсказка
Сгенерируйте каждую из четырёх цифр через random.randint(0, 9) и соберите строку через f-строку.
Ваше упражнение проверяется по этим тестам
import random
import solution
def test():
annotations = solution.generate_pin.__annotations__
assert 'return' in annotations, "You should add a return type annotation"
for seed in [1, 7, 42]:
random.seed(seed)
result = solution.generate_pin()
random.seed(seed)
d1 = random.randint(0, 9)
d2 = random.randint(0, 9)
d3 = random.randint(0, 9)
d4 = random.randint(0, 9)
assert result == f"{d1}{d2}{d3}{d4}"
assert len(result) == 4Решение учителя откроется через:
20:00
