Python вопросы с собеседований
24.9K subscribers
511 photos
16 videos
17 files
408 links
Вопросы с собеседований по Python

@workakkk - админ

@machinelearning_interview - вопросы с собесдований по Ml

@pro_python_code - Python

@data_analysis_ml - анализ данных на Python

@itchannels_telegram - 🔥 главное в ит

РКН: clck.ru/3FmrFd
Download Telegram
🖥 Что особенного в генераторе?

Генератор хранит в памяти не все элементы, а только внутреннее состояние для вычисления очередного элемента. На каждом шаге можно вычислить только следующий элемент, но не предыдущий. Пройти генератор в цикле можно только один раз.

Как объявить генератор
использовать синтаксис (x for x in seq)
оператор yield в теле функции вместо return
встроенная функция iter, которая вызывает у объекта метод __iter__(). Этот метод должен возвращать генератор.
Как получить из генератора список
Передать его в конструктор списка: list(x for x in some_seq). Важно, что после этого по генератору уже нельзя будет итерироваться.

Что такое подгенератор
В Python 3 существуют так называемые подгенераторы (subgenerators). Если в функции-генераторе встречается пара ключевых слов yield from, после которых следует объект-генератор, то данный генератор делегирует доступ к подгенератору, пока он не завершится (не закончатся его значения), после чего продолжает своё исполнение.

На самом деле yield является выражением. Оно может принимать значения, которые отправляются в генератор. Если в генератор не отправляются значения, результат данного выражения равен None.

yield from также является выражением. Его результатом является то значение, которое подгенератор возвращает в исключении StopIteration (для этого значение возвращается при помощи ключевого слова return).

@python_job_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
🖥 Какие методы есть у генераторов ?

🟠__next__() – начинает или продолжает исполнение функции-генератора. Результат текущего yield-выражения будет равен None. Выполнение затем продолжается до следующего yield-выражения, которое передаёт значение туда, где был вызван next. Если генератор завершается без возврата значения при помощи yield, возникает исключение StopIteration. Метод обычно вызывается неявно, то есть циклом for или встроенной функцией next().

🟠send(value) – продолжает выполнение и отправляет значение в функцию-генератор. Аргумент value становится значением текущего yield-выражения. Метод send() возвращает следующее значение, возвращённое генератором, или выбрасывает исключение StopIteration, если генератор завершается без возврата значения. Если send() используется для запуска генератора, то единственным допустимым значением является None, так как ещё не было выполнено ни одно yield-выражение, которому можно присвоить это значение.

🟠throw(type[, value[, traceback]]) – выбрасывает исключение типа type в месте, где был приостановлен генератор, и возвращает следующее значение генератора (или выбрасывает StopIteration). Если генератор не обрабатывает данное исключение (или выбрасывает другое исключение), то оно выбрасывается в месте вызова.

🟠close() – выбрасывает исключение GeneratorExit в месте, где был приостановлен генератор. Если генератор выбрасывает StopIteration (путём нормального завершения или по причине того, что он уже закрыт) или GeneratorExit (путём отсутствия обработки данного исключения), close просто возвращается к месту вызова. Если же генератор возвращает очередное значение, выбрасывается исключение RuntimeError. Метод close() ничего не делает, если генератор уже завершён.

Можно ли извлечь элемент генератора по индексу
Нет, будет ошибка. Генератор не поддерживает метод getitem.

@python_job_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
🖥 Что такое MRO ?

MRO – method resolution order, порядок разрешения методов. Алгоритм, по которому следует искать метод в случае, если у класса два и более родителей.

В классических классах поиск при наследовании по ссылкам на имена осуществляется в следующем порядке:

1. Сначала экземпляр
2. Затем его класс
3. Далее все суперклассы его класса с обходом сначала с глубину, а затем слева направо
Используется первое обнаруженное вхождение. Такой порядок называется DFLR (Обход вглубину и слева направо).

При наследовании классов нового стиля применяется правило MRO (порядок разрешения методов), т.е линеаризованный обход дерева классов, причем вложенный элемент наследования становится доступным в атрибуте mro данного класса. Такой алгорим называется C3-линеаризация. Наследование по правилу MRO осуществляется приблизительно в следующем порядке.

Перечисление всех классов, наследуемых экземпляром, по правилу поиска DFLR для классических классов, причем класс включается в результат поиска столько раз, сколько он встречается при обходе.
Просмотр в полученном списке дубликатов классов, из которых удаляются все, кроме последнего (крайнего справа) дубликата в списке.
Упорядочение по правилу MRO применяется при наследовании и вызове встроенной функции super(), которая всегда вызывает следующий по правилу MRO класс (относительно точки вызова).

Пример наследования в неромбовидных иерархаических деревьях:

class attr = 3 # D:3 E:2
class B(D) pass # | |
class E: attr = 2 # B C:1
class C(E): attr = 1 # / /
class A(B, C): pass # A
X = A() # |
print(X.attr) # X

# DFLR = [X, A, B, D, C, E]
# MRO = [X, A, B, D, C, E, object]

# И в версии 3.х и в версии 2.х (всегда) выводит строку "3"

Пример наследования в ромбовидных иерархаических деревьях:

class attr = 3 # D:3 D:3
class B(D) pass # | |
class C(D): attr = 1 # B C:1
class A(B, C): pass # / /
X = A() # A
print(X.attr) # |
# X

# DFLR = [X, A, B, D, C, D]
# MRO = [X, A, B, C, D, object] (сохраняет только последний дубликат D)
# Выводит строку "1" в версии 3.х, строку "3" в версии 2.х ("1" если D(object))

@python_job_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
🖥 Что такое __new__. И чем он отличается от __init__. В какой последовательности они выполняются ?

Основное различие между этими двумя методами состоит в том, что __new__ обрабатывает создание объекта, а __init__ обрабатывает его инициализацию.

__new__ вызывается автоматически при вызове имени класса (при создании экземпляра), тогда как __init__ вызывается каждый раз, когда экземпляр класса возвращается __new__, передавая возвращаемый экземпляр в __init__ в качестве параметра self, поэтому даже если вы сохранили экземпляр где-нибудь глобально/статически и возвращали его каждый раз из __new__, для него все-равно будет каждый раз вызываться __init__.

Из вышесказанного вытекает что сначала вызывается __new__, а потом __init__

@python_job_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
🖥 Что такое сцепление исключений ?

В Python 3 при возбуждении исключения в блоке except, старое исключение сохраняется в атрибуте данных context и если новое исключение не обработано, то будет выведена информация о том, что новое исключение возникло при обработке старого («During handling of the above exception, another exception occurred:»). Также, можно связывать исключения в одну цепь или заменять старые новыми. Для этого используется конструкция raise новое_исключение from старое_исключение либо raise новое_исключение from None. В первом случае указанное исключение сохраняется в атрибуте __cause__ и атрибут __suppress_context__ (который подавляет вывод исключения из __context__) устанавливается в True. Тогда, если новое исключение не обработано, будет выведена информация о том, что старое исключение является причиной нового («The above exception was the direct cause of the following exception:»). Во втором случае __suppress_context__ устанавливается в True и __cause__ в None. Тогда при выводе исключения оно, фактически, будет заменено новым (хотя старое исключение всё ещё хранится в __context__).

В Python 2 нет сцепления исключений. Любое исключение, выброшенное в блоке except, заменяет старое.

@python_job_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
🖥 Реальное пракическое тестовое задание в команду Assisted team (Python)

Прикрепляем два XML (1 файл, 2 файл) – это ответы на поисковые запросы, сделанные к одному из наших партнёров. В ответах лежат варианты перелётов (тег Flights) со всей необходимой информацией, чтобы отобразить билет на Aviasales.

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

- Какие варианты перелёта из DXB в BKK мы получили?
- Самый дорогой/дешёвый, быстрый/долгий и оптимальный варианты
- В чём отличия между результатами двух запросов (изменение маршрутов/условий)?

Язык реализации: python3 Формат ответа: json Используемые библиотеки и инструменты — всё на твой выбор.

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

@python_job_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
🖥 Что такое type. Как работает поиск метакласса при создании объекта?

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

Когда вы пишете:

class Foo(Bar):
pass

Питон делает следующее:

- Есть ли у класса Foo атрибут __metaclass__?
- Если да, создаёт в памяти объект-класс с именем Foo, используя то, что указано в __metaclass__.
- Если Питон не находит metaclass, он ищет __metaclass__ в родительском классе Bar и попробует сделать то же самое.
- Если же __metaclass__ не находится ни в одном из родителей, Питон будет искать __metaclass__ на уровне модуля.
- И если он не может найти вообще ни одного __metaclass__, он использует type для создания объекта-класса.

@python_job_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
🖥 Вопросы с собеседований python. Как проходит собеседование Python-разработчика: вопросы для джуниоров и мидлов.

Привет! Меня зовут Руслан. Около 12 лет я занимаюсь разработкой, из них девять — на Python. За это время я собеседовался на разные позиции десятки раз и сам провёл примерно пару сотен собеседований. Не всегда успешно :/ В этой статье поговорим о том, как снизить вероятность провалов и к чему быть готовым.

➡️ Читать дальше

@python_job_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
🖥 Как работают метаклассы

- перехватить создание класса
- изменить класс
- вернуть модифицированный

Зачем вообще использовать метаклассы
Основное применение метаклассов это создание API. Типичный пример — Django ORM.

Она позволяет написать что-то в таком духе:

class Person(models.Model):
name = models.CharField(max_length=30)
age = models.IntegerField()
Однако если вы выполните следующий код:

guy = Person(name='bob', age='35')
print guy.age

вы получите не IntegerField, а int, причём значение может быть получено прямо из базы данных.

Это возможно, потому что models.Model определяет __metaclass__, который сотворит некую магию и превратит класс Person, который мы только что определили простым выражением в сложную привязку к базе данных.

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

@python_job_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
🖥 Что такое утиная типизация

Неявная типизация, латентная типизация или утиная типизация (англ. Duck typing) – вид динамической типизации, применяемой в некоторых языках программирования (Perl, Smalltalk, Python, Objective-C, Ruby, JavaScript, Groovy, ColdFusion, Boo, Lua, Go, C#), когда границы использования объекта определяются его текущим набором методов и свойств, в противоположность наследованию от определённого класса. То есть считается, что объект реализует интерфейс, если он содержит все методы этого интерфейса, независимо от связей в иерархии наследования и принадлежности к какому-либо конкретному классу.

Утиная типизация решает такие проблемы иерархической типизации, как:

- невозможность явно указать (путём наследования) на совместимость интерфейса со всеми настоящими и будущими интерфейсами, с которыми он идейно совместим;

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

@python_job_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
🖥 Задача с собеседования Junior

Условие
:

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

Пример:

find_values([11, 10, 3], [10, 3, 5, 11], [11, 10]) -> [11, 10]
find_values([8, 4, 7, "hi"], [8, "hi"], [4, "hi"]) -> ['hi']
find_values([1, 4, 3], [6, 2, 8], ["4", "hi"]) -> []


✔️ Пишите свои решения в комментариях👇

@python_job_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
🖥 Задача с собеседования Junior

Условие
:

Ваша задача — написать функцию, которая проверит, все ли значения увеличиваются на один

Пример:
[-1, 0, 1, 2, 3] -> True
[-1, 0, 1, 3, 4]) -> False
[0, 1] -> True
[1, 0] -> False


✔️ Пишите свои решения в комментариях👇

#задача_с_собеседования

@python_job_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
🖥 Полный список вопросов с собеседований по Python для дата-сайентистов.

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

✔️ Читать дальше

@machinelearning_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
🖥 Задача ходы шахматного ферзя

На шахматной доске 8 х 8 стоит ферзь. Отметьте положение ферзя на доске и все клетки, которые бьет ферзь. Клетку, где стоит ферзь, отметьте буквой Q, клетки, которые бьет ферзь, отметьте звездочками *, остальные клетки заполните точками. Шахматный ферзь может ходить по вертикали, горизонтали и по диагоналям.

Входные данные:

Координаты ферзя на шахматной доске в формате номер столбца (буква от a до h, слева направо) и номер строки (цифра от 1 до 8, снизу вверх).

Пример ввода:

c4

Выходные данные:

Программа выводит стилизованное изображение шахматной доски со схемой возможных передвижений ферзя.

Пример вывода:


. . * . . . * .
. . * . . * . .
* . * . * . . .
. * * * . . . .
* * Q * * * * *
. * * * . . . .
* . * . * . . .
. . * . . * . .


Решение
Способ 1:


x, y, board = *('abcdefgh87654321'.index(i) % 8 for i in input()), range(8)
[print(*['?Q**.'[len({j - x, x - j, i - y, y - i})] for j in board]) for i in board]

Способ 2:

x, y = ('abcdefgh87654321'.index(i) % 8 for i in input())
directions = lambda i, j: (j - i == x - y) + (j + i == x + y) + ((j == x) != (i == y))
[print(*['.*Q'[directions(i, j)] for j in range(8)]) for i in range(8)]

Способ 3:

coor = input()
board = [['.'] * 8 for _ in range(8)]
y, x = 8 - int(coor[1]), ord(coor[0]) - 97
for i in range(8):
for j in range(8):
if (y == i) or (x == j) or abs(y - i) == abs(x - j):
board[i][j] = '*'
board[y][x] = 'Q'
for line in board:
print(*line)


✔️ Пишите свои решения в комментариях👇

@python_job_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
🖥 Задача Единственный выживший

Это вариант классической задачи Иосифа Флавия. В кругу стоят n человек, пронумерованных числами от 1 до n. Начинается расчет, при котором каждый k-й по счету человек выбывает из круга, после чего счет продолжается со следующего за ним человека. Напишите программу, определяющую номер человека, который останется в кругу последним.

Входные данные:

Числа n и k на отдельных строках.

#Пример ввода
9 3

Выходные данные:

Номер последнего оставшегося человека.

#Пример вывода
1

Решение
Способ 1:


n, k = int(input()), int(input())
last = 0
for i in range(1, n + 1):
last = (last + k) % i
print(last + 1)


Способ 2 – рекурсия:

def lastSurvivor(n, k):
if n == 1:
return 1
elif n > 1:
return (1 + (lastSurvivor(n - 1, k) + k - 1) % n)

n, k = int(input()), int(input())
print(lastSurvivor(n, k))


@python_job_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
🌀 20 практических заданий с рекурсией в Python. Python практика.

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

10 Простых заданий + 10 сложных заданий.


✔️ Смотреть

@python_job_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
✔️Задача

Вам будет дано число, и вам нужно будет вернуть его в виде строки в расширенной форме.

Примеры

expanded_form(12) # Должно вернуть '10 + 2' expanded_form(42) #Должно вернуть '40 + 2' expanded_form(70304) # Должно вернуть '70000 + 300 + 4'

Примечание

Все числа должны быть целыми числами больше 0.

👇Свой вариант решения в комментарии


@python_job_interview
🖥 Определение магического квадрата

Магические квадраты издавна интриговали воображение людей: дата изготовления древнейшей сохранившейся таблицы относится к 2200 г. до н.э. Магический квадрат – это квадратная таблица размера n х n, составленная из всех чисел 1, 2, 3 … n2 таким образом, что суммы по каждому столбцу, каждой строке и каждой диагонали равны между собой. Напишем программу, которая определяет, можно ли считать матрицу магическим квадратом.

Входные данные:

Число n, затем n строк с n цифр в каждой.


#Пример ввода
3
8 1 6
3 5 7
4 9 2


Выходные данные:

YES, если введенная матрица является магическим квадратом, и NO в обратном случае.


#Пример вывода
YES

Решение
Способ 1:


n = int(input())
matrix = [list(map(int, input().split())) for _ in range(n)]
if all(i in sum(matrix,[]) for i in range(1, n**2 + 1)):
print('YES' if all(sum(i) == sum(j) == sum([matrix[i][i] for i in range(n)]) == sum([matrix[n-i-1][i] for i in range(n)]) for i in matrix for j in list(map(list, zip(*matrix)))) else 'NO')
else:
print('NO')


Способ 2 – с магической константой и множествами:

n = int(input())
square = [[*map(int, input().split())] for _ in range(n)]
m_const = n * (1 + n ** 2) // 2
print(('NO', 'YES')[all(sum(el) == m_const for x in (((square[i][i] for i in range(n)),(square[i][~i] for i in range(n))), square, zip(*square)) for el in x) and set(sum(square, [])) == set(range(1, n ** 2 + 1))])


@python_job_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
🌀 Заполнение матрицы по спирали

Эта классическая задача часто встречается на собеседованиях и олимпиадах. Рассмотрим несколько способов решения на Python.

На вход программе подаются два натуральных числа n и m. Напишите программу, которая создает матрицу размером n х m, заполнив ее по спирали числами от 1 до n x m. Спираль начинается в левом верхнем углу и закручивается по часовой стрелке.

Пример ввода:

7 6

Пример вывода:

1 2 3 4 5 6
22 23 24 25 26 7
21 36 37 38 27 8
20 35 42 39 28 9
19 34 41 40 29 10
18 33 32 31 30 11
17 16 15 14 13 12

Решение
Способ 1:

n, m = map(int, input().split())
matrix = [[0] * m for _ in range(n)]
dx, dy, x, y = 0, 1, 0, 0

for i in range(1, n * m + 1):
matrix[x][y] = i
if matrix[(x + dx) % n][(y + dy) % m]:
dx, dy = dy, -dx
x += dx
y += dy
for line in matrix:
print(*(f'{i:<3}' for i in line), sep='')

Способ 2:

n, m = (int(i) for i in input().split())
spiral = []
x, y, dx, dy, k = 0, 0, 1, 0, 1
spiral = [[0]* n for _ in range(m)]
for i in range(1, n * m + 1):
spiral[x][y] = i
nx, ny = x + dx, y + dy
if 0 <= nx < m and 0 <= ny < n and spiral[nx][ny] == 0:
x, y = nx, ny
else:
dx, dy = -dy, dx
x, y = x + dx, y + dy
for i in range(n):
for j in range(m):
print(str(spiral[j][i]).ljust(3), end=' ')
print()


Способ 3:


n, m = [int(i) for i in input().split()]
spiral = [[0] * m for _ in range(n)]
c = 1
for k in range(min(n // 2 + 1, m //2 + 1)):
for j in range(k, m - k):
if spiral[k][j] == 0:
spiral[k][j] = c
c += 1
for i in range(1 + k, n - k):
if spiral[i][m - k - 1] == 0:
spiral[i][m - k - 1] = c
c += 1
for j in range(m - k - 2, k - 1, -1):
if spiral[n - k - 1][j] == 0:
spiral[n - k - 1][j] = c


@python_job_interview
📚 20 лучших бесплатных книг по Python для начинающих и продвинутых программистов

Настоящий новогодний подарок всем Python разработчикам.

✔️ Смотреть список

@python_job_interview