Пишем приложение на Python для подготовки к собеседованиям по Python

На конец 2023 года язык программирования Python является самым популярным по индексу TIOBE. Что касается работы, то по количеству вакансий в мире язык Python занимает второе место (после JavaScript/TypeScript). Поэтому у соискателей на должность, где требуется Python, возникает потребность подготовки к собеседованиям.

ab84a34b66f405f2e5d2edb730b36640.png

В этой статье я расскажу о том, как используя Python, можно написать desktop-приложение для ОС Windows, которое поможет быстро, эффективно и абсолютно бесплатно подготовиться к собеседованиям по Python.

Для кого это приложение и какие вопросы будут затронуты

Вы можете подавать резюме на любую профессю, где требуется Python: бекенд-разработчик, аналитик данных, тестировщик, специалист по Data Science или машинному обучению, но в любом случае вы должны обладать необходимой фундаментальной базой. В этом приложении я аккумулировал все возможные вопросы — как вопросы с реальных собеседований (реальные кейсы), так и вопросы, которые, как говорится, вы должны «must know». Все эти вопросы я разбил на 7 тематических групп:

  1. Базовый синтаксис Python (217 вопросов)

  2. Объектно-ориентированное программирование (ООП) (110 вопросов)

  3. Правила оформления кода (PEP8, PEP257) (27 вопросов)

  4. Структуры данных на Python (69 вопросов)

  5. Алгоритмы на Python (39 вопросов)

  6. Git (64 вопроса)

  7. Базы данных и SQL запросы (58 вопросов)

В этом приложении нет фреймворков типа Django или специализированных библиотек типа NumPy. Если интервьюер поймет, что у вас нет фундаментальной базы, то он не будет спрашивать про фреймворки, а собеседование очень быстро закончится.

Также в этом приложении нет задач с LeetCode. В последнее время среди кандидатов осуществляется практика заучивать алгоритмы решения задач на LeetCode, поэтому интервьюеры начали придумывать свои задачи (которые позже попадают на опять же LeetCode).

Тем не менее, в приложении есть классические олимпиадные задачи на основные алгоритмы, но их мало. Уметь решать эти задачи — это своего рода правила хорошего тона в программировании.

Актуальность вопросов

При формировании списка вопросов я старался максимально актуализировать их содержание в соответствии с последними изменениями в синтаксисе языка. Например, существует вопрос про конструкцию match/case, которая появилась не так давно — в Python 3.10.

И наоборот, здесь отсутствуют устаревшие конструкции. Например, кто помнит о функции format () при работе со строками? Когда появились f-строки, о функции format () все забыли, поэтому её здесь и нет. А f-строки есть.

Придумываем функционал приложения

Грубо говоря, функционал приложения — это то, что оно умеет делать. А умеет делать оно следующее: создавать пользователей, вести их статистику (на сколько вопросов они ответили верно, сколько времени они провели на собеседованиях), загружать csv-файлы с вопросами, гибко настраивать собеседования, озвучивать вопросы.

Довольно много получается, поэтому оптимальным вариантом будет использовать парадигму объектно-ориентированного программирования (ООП), но помимо классов и экземпляров будет много-много вспомогательных функций.

Для реализации приложения я использовал самую последнюю версию интерпретатора Python на момент написания статьи — Python 3.12.

Создаем графический интерфейс

Не знаю, как другие разработчики, но мне всегда сначала хочется написать графический интерфейс. И начинаю я с блокнота. Не того, что notepad.exe, а с обычного реального блокнота для рисунков. Вот, что я нарисовал на самом раннем этапе разработки:

Figma бекендера

Figma бекендера

Теперь надо выбрать библиотеку для Python, в которой можно создать графический интерфейс. В Python есть встроенный модуль tkinter. Но если его использовать, то ваше приложении будет похоже на приложения времен Windows 95. Поэтому мы используем что-то современное — стороннюю библиотеку customtkinter. Но почему же не PyQt? Помните принцип KISS? Keep it simple, stupid! Для простого проекта я буду использовать более простые технологии.

Вот что получилось.

edad9ed3256aba3c1fd5ece8b1d72314.png

Пользователи, управление пользователями

Из всех возможных способов реализации управления юзерами в приложении самым оптимальным является создание базы данных. Можно использовать стандартную библиотеку Python sqlite3, но тогда будем писать чистые SQL-запросы в базу данных, а я не хочу. Поэтому давайте используем какую-нибудь популярную ORM. Я выбрал SQLAlchemy. Вот так будет выглядеть код для создания базы данных пользователей:

import os
from typing import Type

from sqlalchemy import create_engine
from sqlalchemy import DateTime, Integer, JSON, String
from sqlalchemy import MetaData
from sqlalchemy.orm import DeclarativeBase
from sqlalchemy.orm import Mapped
from sqlalchemy.orm import mapped_column

from settings import DATABASE_NAME

engine = create_engine(f'sqlite:///{DATABASE_NAME}', echo=False)
metadata = MetaData()


class Base(DeclarativeBase):
    pass


class User(Base):
    """A class representing user's data in the app.

    Attributes:
        __tablename__ (str): The name of the table in the database.
        id: The unique identifier of the user.
        user_name: The name of the user.
        last_enter_date: The date and time of the user's last login.
        interviews_duration: The total duration of interviews
        for the user in seconds.
        progress: The user's progress data stored in JSON format.
    """
    __tablename__ = 'users'

    id: Mapped[int] = mapped_column(primary_key=True)
    user_name: Mapped[str] = mapped_column(String(25))
    last_enter_date: Mapped[Type] = mapped_column(DateTime, nullable=True)
    interviews_duration: Mapped[int] = mapped_column(Integer)
    progress: Mapped[Type] = mapped_column(JSON)


def create_db() -> None:
    """Creates database as a SQLite-file"""
    if not _is_db_created():
        Base.metadata.create_all(engine)


def _is_db_created() -> bool:
    """Checks DB existence in the root folder."""
    return os.path.exists(f'./{DATABASE_NAME}')

Как видно из кода, у нас есть удобный инструмент для хранения прогресса пользователя — формат JSON, а также инструмент для работы с датами и временем DateTime.

Hidden text

Небольшое замечание: с помощью SQLAlchemy также можно работать с базой данных через чистые SQL-запросы.

В приложении мы будем использовать файловую СУБД SQLite — это, пожалуй, самый лучший, если не единственный вариант в данном случае.

Решаем вопрос со списком вопросов

Особого смысла загружать в базу данных список вопросов я не вижу. А что, если у нас список вопросов будет храниться в каком-нибудь файле, который можно будет очень легко править с помощью Microsoft Excel или Google Таблиц. Существует такой текстовый формат CSV, предназначенный для представления табличных данных. Его мы и будем использовать для хранения вопросов. Хорошей новостью является то, что в Python существует инструмент для работы с CSV — одноименная стандартная библиотека. Мы через менеджера контекста открываем файл и переводим данные CSV-файла в битовый поток, и десериализуем этот поток в список кортежей Python.

664c28bab8755ce346dde8880c05d955.png

Имитируем голос интервьюера

Наше приложение может воспроизводить голосом задаваемые вопросы. Эта технология называется TTS (text-to-speech). В Python существует сторонняя библиотека pyttsx3. Проблема в том, что при выполнении чтения текста у нас приложение будет «заморожено» на время воспроизведения. Поэтому давайте переложим выполнение чтения текста на другой поток центрального процессора. Для этого использует стандартную библиотеку threading.

Логика приложения

На данный момент не существует технологии, когда люди что-то наговаривают в микрофон, а нейросеть оценивает, насколько правильно и развернуто они ответили. Тот, кто реализует такую возможность станет миллиардером.

В нашем случае приложение вам задает вопрос, а вы будете, во-первых, учиться слушать вопрос, а, во-вторых учиться отвечать на него, после чего нажмете кнопки «Я правильно ответил на вопрос» и «Я не знаю, следующий вопрос». Но, что если у вас есть сомнений относительно правильности ответа?

Для этого существует третья кнопка — «Посмотреть ответ на вопрос». Нажав на нее, у вас в новом окне появится ответ на вопрос и вы можете посмотреть правильно ли вы ответили или нет.

c7f665f8743082e03163c6eddb37edf0.png

Что можно было сделать лучше

В первую очередь я жалею, что не стал вести разработку через тестирование (англ. test-driven development, TDD). Когда я добавлял новые функции, меня не покидало ощущение, что все ранее созданное сломалось, а запустить pytest или unittest я не могу.

Я также не стал писать «стильный, модный и молодежный» код с использованием библиотеки dataclasses и тамошними декораторами. Поэтому я написал самый обычный код по старинке.

Ну и еще один момент: вы помните, что классы должны быть закрыты для модификации (Open-Closed Principle). Надо было бы сделать все атрибуты приватными и тонко настроить их поведение через геттеры и сеттеры, создав объекты-свойства с помощью декоратора @property. А еще определить коллекцию __slots__ для каждого класса.

Что в итоге получилось

Полный код программы доступен в публичном репозитории в моем профиле на GitHub

Там же вы найдете ссылки на скачивание EXE-версии программы.

А можно на видео показать, как пользоваться приложением

Покажу и расскажу. Вот видео на YouTube. Всем спасибо, всем пока.

© Habrahabr.ru