Реальное ЛАЙВКОДИНГ собеседование JUNIOR Python разработчик

Реальное ЛАЙВКОДИНГ собеседование JUNIOR Python разработчик32:45

Информация о загрузке и деталях видео Реальное ЛАЙВКОДИНГ собеседование JUNIOR Python разработчик

Автор:

Артём Шумейко

Дата публикации:

24.06.2024

Просмотров:

186.5K

Транскрибация видео

Спикер 1

Сегодня вы увидите реальное собеседование на Python backend разработчика, на котором мне предложили 100 тысяч рублей Уже выходила первая часть, обязательно посмотрите ее Там была теория, сегодня будет лайфкодинг, сегодня будет три практические задачи Легкая, средняя и сложная, где нужно реально включать голову и пытаться дойти до решения В прошлом видео ответы были записаны уже после собеседования, и они все были довольно качественные

А сегодня вы посмотрите, как реально я отвечал, ждал, тупил, не мог дойти до какого-то решения.

И, естественно, вам нужно будет ставить видео на паузу и думать, а как бы вы решили эту задачку.

Перед тем, как начать, давайте познакомимся.

Меня зовут Артем, я синер, Python-разработчик, и на этом канале помогаю вам прокачивать хардскиллы и развивать карьеру.

Спикер 2

Поехали.

Так, в общем, вот такая вот функция.

Можешь ли ты описать, что она делает и какие здесь есть замечания?

То есть не переписывая, просто устно проговорить.

Спикер 1

Ага, сейчас посмотрим.

Ну, первое, что в глаза бросается, что типизации нету.

Непонятно, что такое предикат.

Как будто это какая-то функция, потому что она дальше вызывается.

А видно, если я выделяю что-то?

Да, видно.

Вот.

Потом...

Название вроде нормальное.

Неправильно так делать, что задавать дефолтный аргумент изменяемый объект.

Это нужно прописывать уже внутри функции.

If object равно none, тогда он пустой список.

Иначе он будет накапливаться со временем.

значит потом вот эта конструкция создаст нам непонятно что, она вроде как генераторы создает то есть это не работает list comprehension с кортежами так допустим мы хотим создать объекты

Здесь else можно опустить.

В принципе, здесь else и последние две строчки можно убрать, потому что non так и так вернется.

Но, конечно, вот так можно оставить.

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

Ну, вообще, контекста, конечно, не хватает, что здесь происходит.

Ну, вроде так.

Спикер 2

Окей, ну а что делает эта функция?

Спикер 1

Что это за функция?

Она из массива объектов фильтрует их и находит только какие-то подходящие объекты и отдает первый подходящий объект.

Спикер 2

Да, все верно.

Допустим, если я вызову эту функцию...

Будет ли это работать?

Если я вот так вызову эту функцию, какое у нее будет поведение, что она вернет?

Спикер 1

Она вернет, наверное, ошибку, потому что мы не можем у генератора взять нулевой элемент.

Спикер 2

Угу.

Да, все правильно.

Можем тогда переписать на, ну, типа с генератора.

Спикер 1

И вот так имеется в виду?

Спикер 2

Да.

Хорошо.

Окей.

Ну, соответственно, мы переписали на least comprehension, и теперь у нас вроде все работает.

Но если, допустим, я возьму и сделаю... Ну...

Есть ли какие-то способы оптимизировать эту функцию?

Сейчас подумаю.

Спикер 1

В плане эффективности выполнения?

Спикер 2

Да, в плане эффективности.

По памяти, по скорости.

Спикер 1

Ну да, мы здесь, так как мы берем первый элемент, нам как бы не очень-то имеет смысл по всем проходиться.

Так, значит...

Вот так сделаем.

Ну, естественно, если мы найдем подходящий matching object, тогда мы его вернем тут же и по остальным уже не будем их мучить.

Иначе нам придется пройтись по всем и в конце вернуть non, если мы так и не нашли ничего.

Спикер 2

Окей.

Хорошо.

Так, а если вот так мы вызовем эту функцию, что она вернет?

Спикер 1

Сейчас посмотрим.

Значит, у нас в первом случае у нас произойдет true, и нам вернется, по идее, единичка, то есть integer.

Точно.

Немного переслорил.

Сейчас, сейчас.

Так у нас предикат возвращает true или false.

Значит, у нас вернется none, потому что здесь ни один, ни два, ни три, ни четыре.

Сейчас, секунду, сейчас.

Не торопитесь.

Я думаю, вернется в non.

Спикер 2

Ну давай прям голосом проговорим.

То есть object с t равно 1, 2, 3, 4.

Первая итерация цикла, чтобы удержать object.

Спикер 1

Значит, сейчас... Сейчас я верну, что было здесь до этого.

В первый раз у нас будет функция примет единичку, сравнит ее с единичкой и скажет, что у нас true.

Соответственно, object у нас будет true и вернется просто true.

А должен вернуться объект.

Спикер 2

Да.

Топ.

Хорошо.

А какая будет сложность выполнения этой функции?

Спикер 1

В худшем случае O от N. А в лучшем...

От единицы.

Все, окей.

Друзья, здесь нужно пояснить, почему у нас худший вариант от n, а лучший от единицы.

Дело в том, что если у нас на первом месте стоит подходящий нам объект, то мы тут же его провалидируем, что он корректный, функция предикат возвращает true, и мы вернем, собственно, сам объект.

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

То есть у нас, по сути, длина n и o от n получится по времени отработка нашего алгоритма.

Вот такая была первая задачка на собеседовании.

Как вам она?

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

Да, я немножко тупил, да, я немножко молчал, бывало там 10-15 секунд, но тем не менее мы дошли до результата.

Да, с подсказками интервьюера, но обычно так и бывает.

Кстати, если вам сложно определять от единицы, от n, от логарифма, вообще алгоритмическую сложность по времени, по памяти, то заходите в мой Telegram-бот по ссылке внизу и забирайте шпаргалку абсолютно бесплатную для подготовки к алгоритмическим собеседованиям.

Кстати, если вы сейчас готовитесь к техническому собеседованию, скорее всего у вас возникают вопросы «А что меня спросят?

А по каким темам нужно готовиться?

Какие темы точно не нужно готовить, потому что по ним не спрашивают?

Какой у вас сейчас грейд?

Может вы думаете, что вы стажер, а на самом деле вы джуниор плюс или уже мидл?»

И ответы на все эти вопросы собраны в одном едином месте.

Это платформа для подготовки к техническим собеседованиям под названием Solvit.

Мы вместе с командой разработали эту платформу.

На ней есть база вопросов по всем языкам и фреймворкам.

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

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

И по результатам собеседования понимаете, насколько хорошо вы справились, насколько вы умеете отвечать на эти вопросы.

А также в моем прогрессе можете мониторить...

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

Обязательно переходите по ссылке в описании на сайт Solvit, пользуйтесь, развивайтесь и цепляйте самые сочные офферы, так как вы будете лучше других подготовленных к техническому собеседованию.

Итак, теперь вторая задачка.

Задачка у нас была на знание декораторов, как их писать.

Многие видели, как пишутся декораторы, но при просьбе написать их теряются А часто еще просят не просто декоратор написать, а декоратор с параметрами И здесь уже нужна довольно большая вложенность И главное не запутаться, как написать подобный декоратор И прямо сейчас мы это посмотрим Есть вот такая задача

Спикер 2

Декоратором мы передадим, допустим, список таблов, в котором будет k-error.

И, допустим, там, не знаю... Вот, передадим 100 бар.

И, допустим, индекс error мы передадим, не знаю...

вот такой вот то как бы если тут выводит ниц то мы напечатаем один если вы поди двойка то мы напечатаем 2 напишем функцию и

Спикер 1

Она будет принимать параметры.

Здесь будет у нас... Как она называется-то?

Пускай будет wrapper.

Она будет принимать, собственно говоря, функцию.

Сейчас подумаю.

Да, функцию.

И еще будет wrapper1, который будет принимать аргументы, собственно, функции, например, foo, которую мы оборачиваем.

Тут где-то еще уже не помню, где нужно нам...

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

И что мы получаем?

Мы получим, допустим, какой-то exception.

Как бы нам по ним пройтись?

Как бы нам получить список exception?

Я не знаю.

Можешь подсказать, как нам вернуть exception, которая дала функцию?

То есть я, понятно, могу сделать try, но я не знаю, какая длина exception, и я не хочу писать миллион exception.

Вот здесь довольно уникальный случай.

Я вроде бы все это знаю.

Если бы меня никто не спрашивал, я сам бы спокойно написал тот код, который от меня сейчас просят.

Но здесь случился какой-то ступор, и я не смог ответить.

Я так прямо и сказал интервьюеру.

Я не знаю, как это сделать.

Хотя, естественно, я знаю, я умею это делать.

И банально, банальный совет от интервьюера, скорее всего, это был опытный интервьюер, который сказал, ну, просто начни писать, дальше по делу, по ходу поймем.

И я по ходу понимаю, как это реализовать.

То есть часто, если вы на собеседовании, не пытайтесь что-то придумать, пытайтесь просто писать-писать код, может быть, идея придет к вам в процессе.

Я, честно, не знаю, как у нас можно получить exception.

Спикер 2

Окей, а вот exception это что вообще такое?

Типа вот это вот?

Спикер 1

Это класс, который, ну, это объект.

Окей, а от кого он ставится, не знаешь?

От, наверное, baseException.

Ну, окей, а baseException от кого?

Ну, это так просто.

Ну...

Если мы в Python 3, то, может быть, ни от кого.

Спикер 2

Ну, короче, от Type, либо да, ни от кого.

Это самый базовый класс.

Хорошо, то есть это класс.

Есть ли в Python какие-то функции, как мы можем сравнить, является ли под классом или экземпляром класса?

То есть, допустим, тебе пользоваться.

Спикер 1

Да, мы можем.

Я не понимаю, как нам вот здесь, когда мы вызвали функцию, словить эти эксепшены.

Спикер 2

Ну, то есть если мы вот просто так ставим, то будет просто исключение, которое выбросило функцию.

Да.

То есть в любом случае надо его поймать.

Да, я не знаю, как это сделать.

Давай напишем пока просто try accept, и потом посмотрим, может тебе придет в голову мысль, как это делать.

Спикер 1

Угу.

Все, я понял, как это сделать.

Спикер 1

Хорошо.

Вот так.

Спикер 2

Да.

Окей.

Так.

Единственное, что мы не хотим менять поведение функции.

То есть это должно как side effect быть.

Типа, если мы, допустим, вызвали вот так, то есть если я вызову там foo, то я ожидаю, что у меня придет exception, который я выбросил.

Допустим, такой вот.

Просто где-то там попутно печатается print1.

Ну, вернее, печатается 1.

Спикер 1

Ну может быть так?

Спикер 2

Угу.

Да, да.

Окей.

Хорошо, вроде бы всё ок.

А зачем рапс нужен?

Спикер 1

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

Да, да, окей, все работает Третья задача На мой взгляд, самая сложная, самая нетривиальная Потому что декораторы, ну, если ты знаешь, как писать, то ты легко напишешь В первой задаче, ну, легко разобраться довольно А здесь нужно написать целый класс, так еще и с одним необычным условием Здесь даже не важно, на каком языке мы его пишем Важно просто понимать алгоритм Как нужно сохранять данные, как нужно с ними работать

И здесь вы увидите очень интересную концепцию.

Естественно, я также прошу вас поставить на паузу, попытаться решить эту задачку самостоятельно и только потом продолжить просмотр.

Спикер 2

Какая вот задачка.

Надо написать стэк, который поддерживает методы push, pop, top и getmin за постоянное время.

То есть это некий класс...

Надо его реализовать.

Смотри, по операциям push добавляет в стэк, pop достает последний элемент добавленный, top получает последний элемент добавленный без удаления.

Ну, pop, то есть удаляет и возвращает, а top просто возвращает.

И getmin получает минимальный элемент в стэке.

Вот, как бы ты это делал.

Спикер 1

Так.

Давай попробуем написать.

Спикер 2

Можно сразу для простоты.

Мы в стеке храним только Integer.

Спикер 1

Хорошо.

Так, сейчас подумаем.

Здесь самая большая сложность, как я сейчас вижу, это получение минимального элемента.

Нам нужен именно сам элемент, чтобы вернулся, да?

Да.

Вообще, в обычных массивах операция поиск минимального занимает O .

Тут, скорее всего, я бы просто где-то при добавлении новых элементов я бы считал минимальное число.

Ну, минимальный элемент.

Иначе не очень понятно, как...

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

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

Ну тогда, значит, сделаем так Будем добавлять что-то И тут же считать Так, min Значит, self.min Ну, равно... То есть постоянно обновлять это значение, конечно, это будет...

Ну, смотря какая задача, конечно, но для широкой задачи это не очень оптимальная структура данных Поп у нас будет, я не помню, есть ли поп в списке, наверное, есть Да, есть Причем там нам не нужен, это самая история, нам нужно так, наверное Опять же, не помню, но, в общем, можно написать просто Можно минус один убрать, то есть он будет работать А, все, хорошо

Опять же, нам нужно минимально пересчитать, потому что мы удаляем один элемент.

Так, и pop нам возвращает, да, собственно?

Спикер 2

Смотри, сразу внимание акцентирую, что методы push, pop, top и getmin, они все за константы должны работать.

Спикер 1

Это грустно.

Спикер 2

Давай сначала напишем их просто все, а потом будем уже оптимизировать.

Спикер 1

так ну тут можно писать пускай индексировал будет так так проверим что мы написали у нас изначально создается стык атрибут push в него добавляет какое-то число и

и не возвращает ничего pop у нас последнее значение удаляет и возвращает top у нас просто последнее значение возвращает минимальный элемент нам еще нужен так вот здесь интересно по идее мы можем хранить некоторую переменную

И когда у нас происходит push, мы будем сравнивать с этим minimum И понимать, обновляется ли минимальное значение Однако

Однако, когда у нас будет происходить pop, у нас может удалиться минимальное значение, и наше min-num уже не будет содержаться в массиве.

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

Спикер 2

Да, ход мыслей правильный.

То есть одной переменной нам недостаточно.

Переменной, содержащей одно значение.

Спикер 1

Да.

Ну, допустим... Так.

Допустим, пока так сделаем.

Значит, вот у нас сделался push.

и у нас, допустим, каждая minnum уже есть, допустим, есть 3 и 4, а мы пушим 2, тогда нам нужно четверку на двойку будет обновить.

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

Пушит и сработает нормально Но когда мы будем делать поп Допустим, у нас есть 4 и 3 И мы попаем тройку Тогда у нас останется один только атрибут И когда мы будем пушить новый

Нет, стоп.

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

Получается, нам две переменных тоже недостаточно.

Обратите внимание, что здесь я довольно много и долго говорю, озвучиваю свои мысли.

Просто вот как идет мой поток мыслей, так я его озвучиваю.

И это помогает в данном случае.

Было бы плохо, если бы я просто молчал, в голове какие-то пересчитывал варианты.

Блин, а как это сделать?

Два числа, там, три переменные, четыре переменные?

Нет.

Гораздо лучше, когда вы общаетесь, когда слышно вообще, о чем вы думаете.

Потому что кандидат может вообще ни о чем не думать, просто быть в шоке, типа, а что это за задача, как ее решать, я не знаю.

а второй может озвучивать эти же самые мысли и его поддержат, ему дадут какую-то подсказку.

И если вы ведете коммуникацию, да, вы говорите о проблемах, окей, что вы не понимаете, как это решить, но вы говорите об этом.

Это уже половина решения на самом деле.

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

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

Главное в ходе диалога прийти уже к конечному эффективному решению.

Спикер 2

Ну, как бы мыслишь ты правильно, то есть 2 элемента мало, 3 мало, 4 мало, нам нужно иметь какой-то, ну, словом, неограниченный объем этих элементов.

можем его реализовать.

Не могу понять.

Давай тогда дам такую подсказку.

Смотри, допустим, я сделал стэк, я в него засовываю, например, числа 3, 4, 2, 5, 1.

И потом делаю getmin и делаю pop.

Вот.

Что у меня будет возвращаться?

То есть, условно, первый раз делаю getmin, у меня возвращается 1.

Потом я делаю pop.

Потом делаю опять getmin, что будет возвращаться.

Спикер 1

Двойка.

Спикер 2

Двойка.

Потом опять pop.

Ладно, я уже не буду писать.

Давай так.

То есть, вернется единица, двойка, потом делаю getmin.

Спикер 1

Три, четыре, пять.

Спикер 2

Тут еще тоже двойка вернется.

Сначала герпин, потом поп.

не понял еще раз мы сейчас делаем смотри допустим давай я заверну стек чтобы было вот я развернулся так как мы добавили его соответственно теперь я делаю getmin на числе и потом делаю поп этого числа то есть я сделал getmin получил единицу оптимум сделал на то

пятерки getmin получил двойку, попнул пятерку и так далее.

То есть здесь тогда у меня какое получится число?

Спикер 1

Сейчас, секунду.

Тройка.

Спикер 2

Тройка, да.

Спикер 1

Здесь тоже тройка.

Спикер 2

Можем ли мы вот из этой последовательности как-то понять, что нам сделать надо?

То есть мы получили какую-то вот...

то можем мы это применить.

Ну, давай так, какое здесь вообще есть свойство у этой последовательности?

Спикер 1

Ну, она возрастает.

Спикер 2

То есть она сортирована.

Да.

Можно мы как-то ее сформировать?

То есть на уровне кода.

Спикер 1

То есть мы, когда получаем новое число, мы смотрим,

Если оно меньше предыдущего, то мы его добавим.

Нет, сейчас.

Так, тут пока тяжело сформулировать, но на языке, на питоне сейчас попробую.

Значит, когда мы пушим что-то, вот, например, четверку,

Если она больше тройки, то нам она неинтересна.

Если меньше тройки, вот, например, двойка, то мы двойку запишем.

Сейчас я попробую это написать, потом осмыслить.

Так, если список пустой, или вот этот num меньше, чем последний элемент,

Тогда мы добавим сюда этот элемент.

То есть условно у нас добавится тройка, двойка, потом единица.

То есть нам неинтересно.

То есть мы знаем, что когда пятерка попнется, четверка, у нас все равно минимально не изменится элемент.

То есть когда будет попаться... Так, подумаем, подумаем.

А элементы могут повторяться, числа?

Спикер 2

Да, конечно.

Спикер 1

Ага.

Так, значит, вот когда мы делаем pop... Так, какая у нас последовательность-то вот эта?

Pop 0,1?

Так, сейчас.

Ага, значит, у нас по убыванию minnums...

if res равно равно так так, то есть когда мы будем попать где-то наша история вот когда мы удалим единичку

у нас единичка была в конце массива минумс, мы ее дропнули, соответственно, когда мы ее дропнули, у нас минумс, единичка ушла, и последний элемент минумс стал двойкой.

Когда пятерку мы дропнули,

то у нас пятерка не равна двойке, у нас двойка по-прежнему минимальный элемент.

Когда мы ее дропнем, то у нас тройка останется.

Ну вот вроде как-то так она может работать.

За от единицы.

Спикер 2

выглядит хорошо единственная обществе работает но я понял все отлично да все работает вроде бы

Спикер 1

Вот такое собеседование получилось.

Напомню, что мне предложили 100 тысяч рублей на руки по итогам этого и первого собеседования, чему я был, естественно, несказанно рад, будучи сеньор-разработчиком.

И на самом деле очень важно, помимо того, что вы решаете сами задачки, еще...

задавать грамотные вопросы интервьюеру.

То есть у нас минут 5, еще 10 после лайфкодинга были вопросы к интервьюеру.

Первые 20 минут я рассказывал про себя, про свои проекты.

И важно показывать свою заинтересованность, важно показывать, что вы адекватны, что вы умеете делиться какой-то информацией, уточнять какую-то информацию.

Поэтому полная запись этого собеседования будет на моем Boost.

Там уже 5 собеседований, вы покупаете одну подписку и смотрите абсолютно все собеседования.

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

Поэтому, если интересно, присоединяйтесь.

Не забывайте подписываться на все социальные сети, YouTube, ставьте колокольчик, Telegram, там я пишу интересные посты для разработчиков про разработку.

И увидимся в следующих видео.

Пока!