Генератор хранит в памяти не все элементы, а только внутреннее состояние для вычисления очередного элемента. На каждом шаге можно вычислить только следующий элемент, но не предыдущий. Пройти генератор в цикле можно только один раз.
Как объявить генератор
использовать синтаксис (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
Можно ли извлечь элемент генератора по индексу
Нет, будет ошибка. Генератор не поддерживает метод getitem.
@python_job_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
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__
в качестве параметра 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
Прикрепляем два XML (1 файл, 2 файл) – это ответы на поисковые запросы, сделанные к одному из наших партнёров. В ответах лежат варианты перелётов (тег Flights) со всей необходимой информацией, чтобы отобразить билет на Aviasales.
На основе этих данных, нужно сделать вебсервис, в котором есть эндпоинты, отвечающие на следующие запросы:
- Какие варианты перелёта из DXB в BKK мы получили?
- Самый дорогой/дешёвый, быстрый/долгий и оптимальный варианты
- В чём отличия между результатами двух запросов (изменение маршрутов/условий)?
Язык реализации: python3 Формат ответа: json Используемые библиотеки и инструменты — всё на твой выбор.
Оценивать будем умение выполнять задачу имея неполные данные о ней, умение самостоятельно принимать решения и качество кода.
@python_job_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
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
Привет! Меня зовут Руслан. Около 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
Условие:
Ваша задача — написать функцию, которая принимает неограниченное количество списков и возвращает только те элементы, что есть в каждом списке.
Пример:
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
Условие:
Ваша задача — написать функцию, которая проверит, все ли значения увеличиваются на один
Пример:
[-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.
@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
В этой статье мы предложим практические задания для самостоятельного решения на Python. Практика написания кода – лучший способ, прокачать свои навыки.
10 Простых заданий + 10 сложных заданий.
✔️ Смотреть
@python_job_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
✔️Задача
Вам будет дано число, и вам нужно будет вернуть его в виде строки в расширенной форме.
Примеры
expanded_form(12) # Должно вернуть
Примечание
Все числа должны быть целыми числами больше 0.
👇Свой вариант решения в комментарии
@python_job_interview
Вам будет дано число, и вам нужно будет вернуть его в виде строки в расширенной форме.
Примеры
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. Спираль начинается в левом верхнем углу и закручивается по часовой стрелке.
Пример ввода:
Пример вывода:
Решение
Способ 1:
Способ 2:
Способ 3:
@python_job_interview
Эта классическая задача часто встречается на собеседованиях и олимпиадах. Рассмотрим несколько способов решения на 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
Настоящий новогодний подарок всем Python разработчикам.
✔️ Смотреть список
@python_job_interview