Выбраться из матрицы: как пройти отбор на Python-разработчика в Data Science

Обложка: Выбраться из матрицы: как пройти отбор на Python-разработчика в Data Science
Иван Лучко

Иван Лучко, Data Science Team lead в Boosta; Lead Instructor, DevRepublik

У тимлидов разработки не может быть единого шаблона с критериями отбора специалистов в свою команду. Это зависит от многих факторов: необходимого уровня навыков, продукта, с которым предстоит работать, языка программирования, внутренних требований компании. Я работаю тимлидом Data Science команды и хочу поделиться особенностями подбора Python-программистов, которые успел для себя определить. Если вы нацелены стать разработчиком в команде Data Science, эта статья, надеюсь, поможет расширить поле для подготовки.

Программисту в любом случае предстоит работать с командой, и он должен ориентироваться в определенных аспектах Data Science. Поэтому основное внимание (кроме базовых вещей) стоит обращать на те особенности Python, которые важны именно для компании, куда вы хотите попасть. Так, например, наша команда Data Science охватывает широкий спектр задач: начиная с базовой аналитики, выгрузок данных из базы / API, исследования поведения пользователя на основе данных, дизайна и анализа A / B тестов, построения дашборда, автоматизации процессов в компании, используя связку Python и Google SpeadSheets, заканчивая предиктивной аналитикой и построением ML моделей для оптимизации бизнес процессов в продукте. Для охвата такого функционала нужна коллаборация специалистов по различным беграундом. Одну из ключевых ролей в команде играет Python-девелопер.

Почему Trainee и Junior Python-разработчику в Data Science команде будет трудновато?

Для Trainee Python-разработчика наиболее распространенными являются навыки:

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

Это — общие вещи, которые рассматриваются на всех вступительных курсах по Python. Но этого для работы в Data Science будет явно недостаточно. Даже для разминки собеседование с кандидатом скорее всего начнут с «вопросов-баянов» об опыте, которого у Trainee еще не было. Поэтому, проходя отбор, будьте готовы к таким вопросам:

  • Как долго вы используете Python? Расскажите о своем крупнейшем проекте на Python.
  • Как вы следите за последними новостями в мире разработки? Какие ресурсы читаете? Как и где ищете информацию? И делитесь ли своим опытом на Stackoverflow и т.д.?

Далее переходим к вопросам непосредственно на проверку знания Python. С этим, к примеру, Junior уже может справиться, но есть подводный камень. Для Python-разработчика важно не просто понимать теоретические конструкции, но и уметь их применять на практике. Поэтому кандидату на эту позицию следует подготовиться и к таким вопросам:

  • Что такое PEP (Python enhancement proposal)? Какие из них вы знаете? Например, PEP 8, PEP 484.
  • Что такое List и Dict comprehensions?
  • Что такое lambda функции?
  • Как передаются аргументы функций в Python (by value or reference)? Что такое mutable и immutable типы данных? А лучше — приведите примеры.
  • Что значит *args, **kwargs и зачем они используются?
  • Что такое Exceptions, <try-except> и другие опциональные утверждения?
  • Чем отличается процедурная и объекто-ориентированная парадигмы программирования? Основные принципы ООП (наследование, инкапсуляция, полиморфизм).
  • Что значит @classmethod, @staticmethod?

Но почему же тогда «джунам» не стоит еще подаваться в команду разработки Data Science? Основная задача Python-разработчика в Data Science проектах — рефакторинг и доведение прототипов, которые создает команда, до продакшена и поддержка общей архитектуры. Это требует определенного опыта, и на уровне Junior справиться с такой задачей было бы довольно сложно. Часто слабой стороной Junior-ов является качество написанного кода. Обычно на курсах студенты изучают теоретическую основу, и при выполнении практических задач пишут код, который должен просто выполняться. Но не берут фидбэк от более опытных коллег, поэтому над оптимизацией, структурой и соблюдением стилистических принципов приходится работать. По этой причине в основном команды Data Science заинтересованы в Middle- и Senior-специалистах.

К чему стоит готовиться «мидлу»?

От Middle-разработчика тимлид уже может ожидать углубленные знания технических особенностей языка Python и разработки в целом. То есть кандидат должен не просто рассказать, что такое та или иная конструкция, но и вести дискуссию относительно их использования, делиться собственным опытом.

Поэтому перед собеседованием Middle-у стоит проверить себя на:

  • ориентирование в алгоритмах (например, он знает, что такое big-O notation);
  • понимание инженерии и процесса разработки в целом;
  • свободное владение Git;
  • уверенную работу в терминале Linux.
  • способность зайти на внешний сервер и настраивать соответствующую среду.
  • умение построить REST API для микросервиса и задеплоить его в продакшн;
  • следование test-driven подходу в разработке (например, умение качественно покрыть проект unit-тестами).

Так, чтобы проверить теоретические знания Python для уровня Middle, я спрашиваю, например:

  • Что такое Generators? Когда и для чего используются?
  • Что такое аннотация функций?
  • Как вы определите Protected member в Python классе? Что такое @property?
  • Что такое decorator pattern, decorator with parameters (definition using function / class)?
  • Python и multi-threading — это хорошая идея? Каким образом можно запустить код на Python параллельно?
  • Как Python работает с памятью? Опишите Python’s garbage collection mechanism.

Кроме знаний по Python, для Data Science разработчика важно знание SQL, ведь данные — это наше все. Поэтому я всегда даю кандидатам практическое задание по SQL, чтобы проверить, человек просто ориентируется в теории, или умеет использовать ее и имеет практический опыт. Важно не просто уметь извлекать данные из базы и «пушить» их обратно, но и писать сложные многоуровневые оптимизированные запросы, которые проводят предварительную обработку данных на стороне MySQL сервера и работают максимально эффективно.

А еще бонус-совет — кандидат в Data Science команду должен хорошо разбираться в пакетах для обработки и визуализации данных (numpy, pandas и др.) И с основами Machine Learning.

Также полезными будут знания в:

  • Web-Dev.
  • Algorithm.
  • Statistics.

Отличие между Middle и Senior с точки зрения теоретических знаний достаточно условной, поэтому будущий работодатель точно будет смотреть на опыт кандидата, скорость выполнения задач, умение работать с комплексными проектами, знания архитектурных особенностей.

Когда Middle готов стать Senior-ом?

Узнать по теоретическим вопросам, является человек Middle-ом или Senior-ом, сложно. Поэтому, определяя ваш уровень, скорее будут ставить конкретные вопросы о технических решениях из вашего опыта: почему был выбран определенный вариант, как вы доводили его до продакшена, как деплоили и как ориентируетесь в общем флоу деплоймента, DevOps моментах, работе с Docker, Unit -тестов, создании документации, архитектуры и структуры проектов. Senior программист должен уметь строить полноценный проект с нуля, начиная с создания прототипа, заканчивая работающим микросервисом / пакетом с соответствующим CI / CD pipeline деплоймента в продакшен.

На самом деле я не могу сказать, что задаю кандидатам только те вопросы, которые соответствуют их уровню. Уверен, чтобы определить истинную глубину знаний, можно идти и по всем вопросам поочередно. А вдруг кандидат необъективно оценивает собственные возможности?

Еще один, на мой взгляд, универсальный открытый вопрос разработчикам: «Что такое Python и чем он отличается от других языков программирования?». Интересно, что специалисты независимо от уровня отвечают на него совершенно по-разному, и обычно так можно четко понять профессиональный уровень.

Какие практические задачи можно ожидать?

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

Начнем с задачи, демонстрирующей знание и понимание list и dict comprehensions.

Посмотрев на приведенный ниже код, запишите финальные значения A0, A1, … An..

A0 = dict(zip(('a','b','c','d','e'),(1,2,3,4,5)))
A1 = range(10)
A2 = sorted([i for i in A1 if i in A0])
A3 = sorted([A0[s] for s in A0])
A4 = [i for i in A1 if i in A3]
A5 = {i:i*i for i in A1}
A6 = [[i,i*i] for i in A1]
A7 = [i if i%2 else 0 for i in A1 if 2 < i < 8]

','.join(str(j**2) for j in range(10))

Еще один пример — задача, в которой есть 3 функции и выполняются базовые операции (сортировка, фильтрация, возведение массива в квадрат).

Нужно распределить эти 3 функции в порядке возрастания времени, необходимого на их выполнение.

Разместите следующие функции в порядке их эффективности. Все они содержат список чисел от 0 до 1. Список может быть довольно длинным. Примером входного списка может быть [random.random() for i in range(100000)]. Докажите, что ваш ответ правильный.

def f1(lIn):
    l1 = sorted(lIn)
    l2 = [i for i in l1 if i<0.5]
    return [i*i for i in l2]

def f2(lIn):
    l1 = [i for i in lIn if i<0.5]
    l2 = sorted(l1)
    return [i*i for i in l2]

def f3(lIn):
    l1 = [i*i for i in lIn]
    l2 = sorted(l1)
    return [i for i in l2 if i<(0.5*0.5)]

То есть на входе все функции имеют одинаковые данные, на выходе — выдают одинаковый результат. Но из-за того, что внутри операции выполняются в разном порядке, время выполнения будет отличаться. Здесь нужно ориентироваться в алгоритмах и понимать, что происходит непосредственно с твоими данными в процессе выполнения. Эту задачу может выполнить Junior, а может не выполнить и Middle. Казалось бы, такая мелочь, но когда мы работаем с большим количеством данных, важно, чтобы код был оптимизирован и программа выполнялась максимально быстро.

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

Также профиль на GitHub — это плюс в резюме. Но советую представлять только написанный именно вами код. Ведь, даже с учетом общепринятых стандартов, каждый программист имеет собственную стилистику написания, узнаваемую логику и ход мыслей. И опытный тимлид обязательно увидит разницу.

Именно с этим фактором у меня связано несколько курьезных ситуаций, когда кандидаты пытались представить ворованный код за свой. Был даже Middle-специалист с очень сильным профилем, приславший примеры работ, которые отличались стилистически. Я попытался вбить отправленный им код в Google-поиск, и, как оказалось, он был написан программистом с Индии. С такими людьми редко доходят даже до собеседования, ведь в работе с данными любая фальсификация недопустима.

И напоследок, один из основных советов — уделите время решению практических задач на Python и SQL. Ведь на собеседовании основная цель кандидата — не решить задачу, которую вам предложат, а не растеряться и не запутаться в синтаксисе, когда вас попросят написать 2 строки кода. Большинство программистов пишут код в IDE, а вот на собеседовании скорее предложат лист бумаги и ручку. Поэтому хорошей идеей будет освежить в памяти и основные теоретические моменты Python, и синтаксические конструкции. Особенно это важно, если у вас был перерыв в работе.