February 17, 2022

Python собес

Вопросы к собеседованию по python

Топ вопросов на собеседовании python developer v.220714

1. Генератор и итератор?

Генератор это частный случай итератора. Итератор представляет собой любой объект, класс которого имеет методы __next__ и __iter__. Генератор – это итератор, который обычно создается путем вызова функции, содержащей не менее одного оператора yield. Это ключевое слово действует аналогично return, но возвращает объект-генератор.

Между ними существуют тонкие различия:
Для генератора мы написали функцию, а для итератора можно использовать встроенные функции iter() и next().
Для генератора используется ключевое слово yield для выдачи по одному объекту за раз.


В генераторе может быть сколько угодно операторов yield.
Генератор сохраняет текущее состояние локальных переменных (local variables) каждый раз, когда yield приостанавливает цикл (loop). Итератор не использует локальные переменные, он работает только с итерируемым объектом (iterable).
Итератор можно использовать с помощью класса, а генератор — нет.
Генераторы работают быстро, компактно и проще.
Итераторы экономнее потребляют память.

1.2 Что сделать с классом, чтобы он стал итерируемым(iterable)? Чтобы создать объект/класс в качестве итератора, вам необходимо реализовать методы __iter__() и __next__() для объекта + StopIteration, чтобы итерация не была бесконечной.

class MyNumbers:
    def __iter__(self):
        self.a = 1
        return self
    
    def __next__(self):
        if self.a <= 20:  
            x = self.a
            self.a += 1
            return x
        else:
            raise StopIteration

List, tuple, dict и sets — это все итерируемые объекты. Они являются итерируемыми контейнерами, из которых вы можете получить итератор. Все эти объекты имеют метод iter(), который используется для получения итератора.


2. Лямбда или анонимная функция? Расскажите про выражения лямбда (lambda expressions). Где они могут пригодиться?

Если нужно написать функцию с одним выражением, то можно обойтись без определения и сделать ее анонимной. Выражение лямбда может принимать входные данные и возвращать значения. Пример функции, представленной в виде выражения лямбда:
В данном примере входные данные обозначаются переменными a и b. То есть, если a > b, то возвращается a, в противном случае возвращается b. В качестве аргументов используются 3 и 3.5.
Лямбда позволяет обойтись без входных данных.

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

3. Типы данных в python

None (неопределенное значение переменной)

Числа (Numeric Type)
bool - Логические переменные (Boolean Type) [ 1 or 0]
int – целое число [ 123 ]
float – число с плавающей точкой [ 1.23 ]
complexкомплексное число [ 3 + 7j ]
decimal - десятичные
fraction - дробные

Списки (Sequence Type)
list – список [1, 2, 3]
tuple – кортеж (1,2,3)
range – диапазон range(3,9,2)

Строки (Text Sequence Type )
str Бинарные списки (Binary Sequence Types)
bytes – байты
bytearray – массивы байт
memoryview – специальные объекты для доступа к внутренним данным объекта через protocol buffer

Множества (Set Types)
set – множество {1,2,3}
frozenset – неизменяемое множество (неизменяемая версия set)

Словари (Mapping Types)
dict – словарь {1:1, 2:2, 3:'z'}

Неизменяемые: int, float, bool, string и tuple, bytes, complex, frozenset
Изменяемые: list, dict и set, bytearray

python кэширует целые числа от -5 до 256

а строки интернируются: 1)длиной 0 или 1, 2)до 4096(20)сим, 3)имена

3.2 Type hints (аннотации типов) позволяют явно указать тип для переменной. хранятся в словаре __annotations__. тоже самое возможно для функций и классов.

Компоновщики для аннотаций:
Optional[...] — указаный тип и None

Union[...] — принимает только разрешенные в этом списке

Any — любой тип

Аннотации коллекций: Sequence, Dict, List, Tuple, Set

Literal[...] - равно одному из ЗНАЧЕНИЙ

TypedDict — типизированный словарь

NoReturn -- безвозвратная функция

Final -- переменная не должна быть повторно назначена или переопределена

4. Что такое магические методы(dunder)?

Так называют специальные методы, обрамленные двумя подчеркиваниями. Магические методы представляют простой способ заставить объекты вести себя аналогично встроенным типам. Это, в частности, позволяет стандартизировать поведение базовых операторов с экземплярами класса.
подробнее: https://habr.com/ru/post/186608/

*Перегрузка оператора – это возможность переопределять различные операторы в классах, то есть менять операции, которые они выполняют, в зависимости от контекста. В Python есть операторы такие как: сложение, вычитание и т. д., которые можно перегрузить для класса.

5. Разница между __new__ и __init__?

Метод __new__ используется, когда нужно управлять процессом создания нового экземпляра, а __init__ – когда контролируется его инициализация. Поэтому new возвращает новый экземпляр класса, а init – ничего.

6. Что такое id или id()?

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

7. Как получить список всех атрибутов объекта или что такое dir()?

В простейшем виде с помощью функции dir().
Для объектов, класс которых не определил __dir__(), функция попытается определить атрибуты по данным __dict__.
Возвращаемый список может включать не все атрибуты, особенно в случаях с переопределенным __getattr__().
Функция help() показывает строку документации и справку для ее аргумента
Функция dir() возвращает список, содержащий пространство имен в объекте


8. Что быстрее dict, list, set, tuple?

Средняя временная сложность поиска в множествах и словарях соответствует O(1), в случае последовательностей(напр. список) O(n). Кортежи – это неизменяемый тип, поэтому они могут давать выигрыш в скорости перед списками.

8.2 Какая разница между словарями и JSON?
Dict (словарь) — это тип данных Python, представляющий собой набор индексированных, но неупорядоченных пар ключ-значение.
JSON — просто строка, которая следует заданному формату и предназначена для передачи данных.

9. Какая разница между одинарным (_) и двойным (__) подчеркиванием? Почему игнорируются имена-идентификаторы, которые начинаются с символа подчеркивания?

В питоне не реализована концепция скрытой переменной (private variable), поэтому принято декларировать скрытые переменные первым символом в виде нижнего подчеркивания.

Одинарным (protected) подчеркиванием задаются частные переменные, функции, методы и классы. Двойное подчеркивание(private) применяется для искажения имен атрибутов в классе (вызвать такой метод стандартным образом не получится).

10. Как в Python воплощены public, private, protected методы?

Этот вопрос напрямую связан с предыдущим. Все компоненты класса Python по умолчанию являются открытыми (public). Для защищенных (protected) методов по соглашению Python добавляется префикс одиночного подчеркивания, для закрытых (private) методов – префикс двойного подчеркивания

11. Что такое MRO?

MRO – сокращение от method resolution order. То есть это способ разрешения проблемы множественного наследования классов. Для конструирования линеаризации класса в версиях Python с новым стилем классов используется алгоритм C3 линеаризации.

class A1:
    def hi(self):
        print("A1")

class A2:
    def hi(self):
        print("A2")

class B(A1, A2):
    def hi(self):
        print("B")
 
class C(A1, A2):
    def hi(self):
        print("C")
 
class D(B, C):
    pass
 
d = D()
d.hi()

*Эта ситуация, так называемое ромбовидное наследование (diamond problem) решается в Python путем установления порядка разрешения методов. В Python3 для определения порядка используется алгоритм поиска в ширину, то есть сначала интерпретатор будет искать метод hi в классе B, если его там нету - в классе С, потом A1 и A2(слева направо).


12. Для чего в Python используются слоты?

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


13. Что такое контекстные менеджеры? Где они применяются? Как создать свой контекстный менеджер? Что такое with в питоне?

Данная инструкция обеспечивает исполнение кода очистки после исполнения программы. Например, можно использовать ее для открытия файла, совершить с ним какие-то действия и автоматически закрыть файл после завершения работы. Аналогичным образом можно открывать соединение с базой данных и автоматически его закрывать. Код очистки исполняется даже в случае, когда появляется исключение (exception).
Контекстные менеджеры – это конструкции, которые упрощают работу с тем или иным интерфейсом. Например, работу с файлами или базами данных. Создаются они с помощью оператора with. Для создания собственного класса контекстного менеджера используется библиотека contextlib.


14. Что такое декораторы с параметрами? Декоратор Это обёртка вокруг функции, которая меняет её поведение. Сам по себе декоратор является вызываемым объектом (функция или класс с __call__).

Они позволяют менять поведение другого объекта, при этом ничего не меняя внутри. Код благодаря этому становится проще и более гибким.

Декоратор позволяет добавить новую функциональность к существующей функции. Это делается следующим образом. Функция передается декоратору, а он выполняет и существующий, и дополнительный код.
В качестве декоратора можно использовать выражение, значение которого – функция, принимающая и возвращающая функцию. А значит, можно создавать декораторы с параметрами (фабрики декораторов).
https://habr.com/ru/company/wunderfund/blog/657355/

14.1 Напишите декоратор отображающий время исполнения функции

import time
def timer_decorator(func):
    def wrapper(*args, **kwargs):
        start_time = time.monotonic()
        res = func(*args, **kwargs)
        print(time.monotonic()-start_time)
        return res
    return wrapper

@timer_decorator
def func1():
    time.sleep(2)
    return 'ok'

print(func1())

15. Чем отличаются и как используются декораторы @classmethod и @staticmethod?

Базовые декораторы classmethod, staticmethod используются для методов, определённых внутри классов. В метод класса первым аргументом передаётся класс. Аналогично метод экземпляра в первом аргументе получает сам экземпляр. Статичный метод используется в том случае, когда метод не имеет доступа к тому, что представляет собой класс или объект класса.

15.2 В чем разница между методами экземпляра, класса и статическими методами в Python?

- Методы экземпляра: принимают параметр self и относятся к определенному экземпляру класса.
- Статические методы: используют декоратор @staticmethod, не связаны с конкретным экземпляром и являются автономными (атрибуты класса или экземпляра не изменяются).
- Методы класса: принимают параметр cls, можно изменить сам класс.

15.3 Что означает self в классе?

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

16. Что такое дескриптор?

Дескриптор – атрибут объекта, чьё поведение при доступе переопределяется методами __get__, __set__ и __delete__. Если определен хотя бы один из этих методов, объект становится дескриптором.

17. Что такое метаклассы в Python?

В Python классы являются объектами, поэтому они сами должны чем-то генерироваться. Эти конструкции представляют собой своеобразные «классы классов» и называются метаклассами. Примером встроенного метакласса является type. В основном метаклассы используются для создания API. Подробнее читайте в нашей публикации.
18. Как вы тестируете код? Что такое mock? Что такое Pytest?
Для модульного тестирования используется unittest или Pytest. Mock – это специальный модуль (ставший недавно частью стандартной библиотеки) для тестирования без существенной адаптации кода под тесты.

19. Как проводится отладка программ на Python?

В Python есть модуль pdb. Он позволяет пошагово провести отладку программы. В версии 3.7 появилась функция breakpoint(), которая также облегчает дебаггинг.



20. Что такое PEP8?

Python Enhancement Proposal — Соглашение о том, как писать код на Python. Это официальный проектный документ, предоставляющий информацию сообществу Python и описывающий новую функцию для Python или его процессов. PEP 8 важен, так как документирует руководящие принципы стиля для кода Python. То есть, для написания кода ввели определенные правила, которым рекомендуется следовать.



21. Какие есть программы для проверки стиля кода? Каковы их преимущества и недостатки?

Скажем, pylint, pyflakes. Наиболее популярные инструменты мы уже описали и сравнили.

22. В чём состоит отличие процессов от потоков?

ПРОЦЕСС (Process) — экземпляр программы во время выполнения, независимый объект, которому выделены системные ресурсы

ПОТОК (Thread) — Последовательность операций которым управляет ОС. Это определенный способ выполнения процесса. Когда один поток изменяет ресурс процесса, это изменение сразу же становится видно другим потокам этого процесса.
Главное отличие в том, что Потоки делят одно и тоже пространство памяти. А процессы для этого нужно "связывать" между собой.

Модули subprocess и threading. Использование нескольких процессов аналогично использованию нескольких независимых программ, обмен данными организован через каналы. Если приложение должно выполнять несколько задач в одно и то же время, используются потоки (threads). В этом случае для ограничения доступа потоков к памяти в Python имеется блокировщик GIL.

GIL (Global Interpreter Lock) — глобальная блокировка интерпретатор, накладывающая некоторые ограничения на потоки. А именно, нельзя использовать несколько процессоров одновременно.

еще про gil

23. Что такое AsyncIO? Когда его имеет смысл использовать?

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



24. В чем заключается проблема циклических зависимостей? Как ее решить?

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



25. Как реализовать шаблон Singleton на Python? Какие есть альтернативы?

Стандартный пример описан в примерах PEP-0318. Менее удобна для тестирования реализация через декоратор, элегантнее вариант через метаклассы.

26. Какие шаблоны (Паттерны) проектирования вы еще знаете? Какими пользовались?

Фабричный метод, абстрактная фабрика, прототип, компоновщик, итератор.
Хабр: Шпаргалка по шаблонам проектирования

Рефакторинг.гуру Паттерны

Почему не нужны шаблоны проектирования в Python

Dependency injection


27. Основные фичи питона?

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

28. В чем разница между списком(list) и кортежем(tuple)?

List и Tuple - это типы данных, которые хранят коллекцию объектов в Python. Объекты, хранящиеся в обеих последовательностях, имеют разные типы данных. List представлены квадратными скобками ['sara', 6, 0.19], а tuples - круглыми скобками ('max', 5, 0.97)

Основная разница в том, что список может изменяться (mutable), а кортеж не может (immutable).Это означает, что данные в list могут быть изменены, добавлены или нарезаны на ходу, а в tuples остаются неизменными и не могут быть изменены никаким образом.

  1. Список можно изменить после создания.
  2. Кортеж нельзя изменить после создания.
  3. Список упорядочен. Он представляет собой упорядоченные последовательности объектов, как правило, одного и того же типа. Например, все имена пользователей упорядочены по дате создания: [«Seth», «Ema», «Eli»].
  4. У кортежа есть структура. В каждом индексе могут сосуществовать различные типы данных. Например, такая запись базы данных в памяти: (2, «Ema», «2020–04–16») # id, name, created_at.



29. Как в питоне работает трёхместный (тернарный) оператор?

В питоне есть такие выражения:

[если верно] if [выражение] else [если неверно]

То есть, когда выражение верное (True), то исполняется код [если верно]. В остальных случаях исполняется код [если неверно].

30. Питон чувствителен к регистру?

Язык считается чувствительным к регистру в случае, если он различает имена "myname" и "Myname". То есть, если он отслеживает разницу регистра (между верхним и нижним). Посмотрим, как с этим в питоне.

31. Предельно допустимая длина идентификатора в питоне?

В питоне идентификатор может быть любой длины. Помимо этого есть несколько правил для присвоения имен:
- первым символом может быть нижнее подчеркивание (_), символы A-Z или a-z;
- остальная часть имени может состоять из символов A-Z/a-z/_/0-9;
- не забываем, что питон чувствителен к регистру;
- в качестве имени нельзя использовать ключевые слова (keywords):
and, def, False, import, not, True, as, del, finally, in, or, try, assert, elif, for, is, pass, while, break, else, from, lambda, print, with, class, except, global, None, raise, yield, continue, exec, if, nonlocal, return.


32. Как можно преобразовать строку (string) в нижний регистр (lowercase)?

Для этого используется метод lower(). Для преобразования в верхний регистр (uppercase) используется метод upper(). Еще есть методы isupper() (все символы в верхнем регистре) и islower() (все символы в нижнем регистре), которые проверяют регистр всех символов имени. Еще есть метод istitle(), который проверяет строку на стиль заголовка (все слова должны начинаться с символа в верхнем регистре)

33.1 Для чего нужен pass (pass statement) в питоне?

Pass - представляет собой нулевую операцию в Python. Обычно она используется для заполнения пустых блоков кода, который может выполняться во время исполнения. В примере, приведенном ниже, без оператора pass можно столкнуться с ошибкой как <<IndentationError>> во время выполнения кода.

33.2 Зачем нужны break и continue?

Они используются для управления последовательностью операций: break останавливает исполнение цикла и переводит исполнение на следующий блок кода, continue как бы перепрыгивает на следующую итерацию цикла и не прекращает его исполнение. Иногда нужно, чтобы код не давал никакого результата и не показывал ошибку, например, если еще не готово, но нужно иметь синтаксический корректный код. Можно поставить pass. Кроме него есть break (break statement), которое разрывает цикл. Наконец, есть continue (continue statement), которое перешагивает на следующую итерацию.

34. Как получить список из всех ключей словаря (dictionary keys)?

На такие вопросы нужно отвечать детально, с примерами. Данная задача выполняется с помощью функции keys()
35. Что такое срез?
Срез — это методика, которая позволяет получить часть списка, кортежа или строки.

36. Как пишутся комментарии в питоне?

Для этого используется символ #. Все, что написано на строке после него, считается комментарием и игнорируется. Комментарии используются для объяснения цели написанного кода. Многострочных комментариев в прямом смысле слова в питоне нет.

37. Как проверить, что все символы строки относятся к алфавитно-цифровым?

Для этого используется метод isalnum().


38. Как перевести первый символ строки в верхний регистр?

Для этого есть метод capitalize()


39. Минусы и недостатки python?

Какие в питоне есть ограничения:
- интерпретируемая природа питона снижает скорость исполнения программы
- его не выгодно использовать для мобильных устройств и браузеров
- будучи языком с динамической типизацией данных, он использует утиную типизацию; в связи с этим появляются ошибки исполнения (runtime errors);
- в нем слабо развиты возможности доступа к базам данных; поэтому питон не идеальный вариант для приложений с очень большими базами данных;
- низкие требования на входе, то есть свои силы в питоне может попробовать каждый; это иногда снижает качество кода;
- у питона индивидуально выраженный стиль.

40. Как в питоне узнать, в какой мы сейчас директории? Как узнать текущую директорию в питоне?

Для этого используется функция getcwd(). Она импортируется из модуля os


41. Что такое приглашение интерпретатора (interpreter prompt)?

Когда мы заходим в интерпретатор питона, то видим следующую строку:
>>>


42. Что нужно сделать, чтобы функция возвращала значение?

Для этого используется ключевое слово return.


43. Что такое блок?

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

44. Если мы не поставим двоеточие в конце строки для цикла "do-while", он все равно сработает?

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

45. В каких областях питон имеет преимущество, лучше всего использовать?

Лучше всего питон использовать в следующих областях:
- веб-приложения
- графические интерфейсы пользователя для настольных ПК
- научные и арифметические приложения
- разработка ПО
- разработка программ обучения
- приложения для бизнеса
- сетевые приложения
- игры, 3D-графика


46. Можете назвать десять встроенных функций питона?

Функция complex() создает комплексное число
Функция eval() исполняет строку.0) — min(2,3)
Функция filter() отфильтровывает элементы, для которых заданное условие верно.
Функция format() помогает задать формат строки:
Функция hash() возвращает хэш-значение объекта:
Функция hex() преобразовывает число в шестнадцатеричное число:
Функция input() читает ввод и возвращает строку:
Функция len() возвращает число, показывающее длину строки:
Функция locals() возвращает словарь с локальной таблицей имен
Функция open() открывает файл

46.2 Встроенные математические функции:
pow(в степень), abs(модуль), round(округ.), int(челое), hex(к шестнад-ричн.), bin(к двоич)...

операции выражений:
+, -, /, , *, &

служебные модули:
random, math


47. Как конвертировать список в строку?

Для этого подойдет метод join()

47.2 Как развернуть список?

Обратите внимание, что reverse() вызывается в списке и изменяет его. Сама функция не возвращает измененный список.

48. Как убрать из списка дубликат элемента?

Для этого можно конвертировать список во множество (set)


49. Можете объяснить жизненный цикл треда?

Общими словами, цикл выглядит так:
- сначала создается класс, который подменяет метод исполнения класса в треде, и создаем экземпляр (instance) для этого класса;
- вызываем start(), который готовит тред к исполнению;
- переводим тред в состояние исполнения;
- можно вызвать разные методы, например sleep() и join(), которые переводят тред в режим ожидания;
- когда режим ожидания или исполнения прекращается, другие ожидающие треды подготавливаются к исполнению;
- после завершения исполнения тред останавливается.


50. Что такое словарь (dictionary)?

Словарь содержит пары типа "ключ: значение"
расскажите про арифметические операторы //, %, и **
Оператор // выполняет целочисленное деление и возвращает целую часть числа, полученного в результате операции
Оператор ** возводит в степень
Оператор % возвращает результат деления по модулю, то есть остаток после деления

51. Что вам известно про операторы сравнения в питоне?

Данные операторы сравнивают значения между собой.
Оператор "меньше" (<): если значение с левой стороны от оператора меньше, он возвращает True:
Оператор "больше" (>): если значение с левой стороны от оператора больше, он возвращает True:
Оператор "меньше или равно" (<=): если значение с левой стороны от оператора меньше значения с правой стороны или равно ему, он возвращает True:
Оператор "больше или равно" (>=): если значение с левой стороны от оператора больше значения с правой стороны или равно ему, он возвращает True:
Оператор равенства (==): если значения равны, он возвращает True:
Оператор неравенства (!=): если значения не равны, он возвращает True:

51. Что такое операторы присвоения в питоне?

Все арифметические операторы можно комбинировать с символом присвоения =, *=

52. Расскажите про логические операторы в питоне.

Всего их три: and, or, not

53. Что такое оператор принадлежности?

Это операторы in и not in. Они показывают, является ли одно значение частью другого.

54.1 Расскажите про операторы тождественности.

Операторы is и is not показывают, являются ли два значения идентичными.

54.2 В чем разница между “is” и “==”?

<is> проверяет идентичность(id), а < == > проверяет равенство значения.

55. Что такое битовые операторы?

Данные операторы выполняют операции в битовом формате.
% ^ >>

54. Что такое строка документации (docstring)?

Она вносится первой строкой в блок, определяющий содержание функции, класса или метода. Содержит описание их цели и способа исполнения. Обозначается тремя одинарными или двойными кавычками с каждой стороны.
__doc__

55. Как можно конвертировать строку в число?

Если строка содержит только числовые символы, можно использовать функцию int()

56. Как можно принять результат ввода на клавиатуре?

Если пользователь что-то вводит с помощью клавиатуры, можно использовать функцию input(). В качестве аргумента можно задать данной функции текст запроса на ввод. Результат ввода всегда является строкой.

57. Что такое рекурсия? Может ли рекурсия создавать сложности? Какие преимущества у рекурсии?

Это когда функция вызывает саму себя. При этом она должна иметь базовое условие, чтобы не создать бесконечный цикл
Разумеется:
Приходится чаще вызывать функцию.
Каждый вызов функции сохраняет переменную состояния в программном стеке, то есть растет потребление памяти, что в итоге может стать причиной переполнения памяти.
Вызовы функции отнимают время.

Рекурсия помогает:
экономить усилия на выполнение задачи,
сократить объем кода по сравнению с циклами,
легче воспринимать код.

58. Что делает функция zip()?

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

59. Как посчитать длину строки (string)?

Для этого вызываем функцию len()


60. Расскажите про генераторы списков (list comprehension)

Это упрощенный подход к созданию списка, который задействует цикл for, а также инструкции if-else для определения того, что в итоге окажется в финальном списке. Они позволяют создавать списки с помощью одной строки кода

три основных преимущества.

  1. Простота. List comprehension позволяют избавиться от циклов for, а также делают код более понятным.
  2. Скорость. List comprehension быстрее for-циклов, которые он и заменяет. Это один из первых пунктов при рефакторинге Python-кода.
  3. Принципы функционального программирования — это подход, при котором изменяемые данные не меняются. Поскольку list comprehensions создают новый список, не меняя существующий, их можно отнести к функциональному программированию.
odd_squares = [n*n for n in nums if n%2 == 1]

61. Как можно получить все значения из словаря?

Для этого используется метод values()


62. Как можно переключить регистр строки?

Можно использовать метод swapcase(), предусмотренный для класса str


63. Для чего используется bytes()?

Это встроенная функция питона, которая возвращает неизменяемый байтовый объект


64. Что такое оператор контроля последовательности (control flow statement)?

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


65. Как работать с числами, которые не входят в десятичную систему счисления?

В питоне можно вводить бинарные, восьмеричные и шестнадцатеричные числа.
Бинарные. Это числа, составленные из 0 и 1. Для ввода в бинарном формате, используется префикс 0b или 0B:
Число можно преобразовать в бинарный формат с помощью функции bin():
Восьмеричные числа могут состоять из цифр от 0 до 7, также используется префикс 0o или 0O:
Шестнадцатеричные числа могут состоять из цифр от 0 до 15, также используется префикс 0x или 0X:

66. Чем Python отличается от Java? Сравнение Python с другим языком Если сравнивать Python и Java:

- Java быстрее - Python использует отступы, а Java нужны скобки - в Python динамическая типизация, а в Java — статическая - Python — простой и лаконичный, а Java — многословный язык - Python — интерпретируемый язык - Java не зависит от используемой платформы - в Java есть интерфейс JDBC, который улучшает доступ к базам данных

67. Как выйти из бесконечного цикла?

Можно нажать комбинацию клавиш Ctrl+C, которая прерывает исполнение.

68. Как исполняется код в питоне?

Файлы питона сначала компилируются в байткод, который затем исполняется


69. Расскажите, какой в питоне механизм передачи параметров.

В питоне используется передача параметров по ссылке. Если изменить параметр внутри функции, то это отразится на выводе функции. Однако, если использовать в качестве параметров литералы (строки, числа, кортежа), то они передаются по значению (потому что они не изменяемые).


70. Чем файл .pyc отличается от .py?

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

71. Что делает питон объектно-ориентированным? ООП

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

72. Когда в блоке try-except исполняется элемент else?

В блоке if-else элемент else исполняется в случае, если условие в операторе if (if statement) является неверным (False). А вот в блоке try-except элемент else исполняется только в случае, если элемент try не выдает исключение.

try:
    # попробовать сделать это
except:
    # если блок try не сработал, попробовать это
finally:
    # всегда делать это

73. Что такое переменная PYTHONPATH?

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

74. Расскажите про функции join() и split() в Python.

Функция join() позволяет соединять символы строки (string), чередуя с указанным символом. Функция split() позволяет разделить строку, чередуя символы с указанным символом.

75. Приведите несколько методов, с помощью которых можно реализовать в питоне функционально ориентированное программирование.

Несколько методов могут помочь с итерацией по списку (list).
- filter() может отфильтровать несколько значений на основе условия.
- map() применяет функцию к каждому элементу итерируемого объекта.
- reduce() продолжает уменьшать последовательность (sequence) парами, пока не будет достигнуто единичное значение.

75.2 Объясните, как работает функция reduce

reduce принимает функцию и последовательность — и проходит по этой последовательности. На каждой итерации в функцию передаются как текущий элемент, так и выходные данные предыдущего элемента.

75.3 Объясните, как работает функция filter

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

Каждый элемент передается функции, которая включает его в последовательность, если по условию получает True, и отбрасывает в случае False

75. Можно ли сказать, что del и remove() — это одно и то же? Что это такое, в целом?

del и remove() — это методы для списков, они нужны для удаления элементов
del позволяет удалять элементы под конкретным индексом, а remove() позволяет удалять элементы на основе их значения.

76. Какие различия есть между методами для списков append() и extend()?

Метод append() добавляет элемент к концу списка, а метод extend() добавляет к концу списка переданный ему итерируемый объект (iterable).


77. Какие есть режимы обработки файлов в Python?

Предусмотрены следующие режимы:
только чтение – ‘r’
только запись – ‘w’
чтение-запись – ‘rw’
добавление в конце – ‘a’
Можно открыть текстовый файл с опцией ‘t’. Поэтому, чтобы открыть текстовый файл для чтения, можно использовать режим ‘rt’. Точно так же для бинарных файлов используется ‘b’.

78. Что делает функция map()?

Функция map() возвращает итератор, который применяет функцию, переданную ей в первом аргументе, ко всем элементам итерируемого объекта (iterable), переданного ей во втором аргументе.


79. Расскажите про try, raise и finally.

Это ключевые слова (keywords) для обработки исключений (exception handling). Потенциально рискованный код помещается в блок try, оператор raise (raise statement) используется для прямого вызова ошибки, а в блоке finally находится код, который исполняется в любом случае.


80. Что случится, если не обработать ошибку в блоке except?

Если этого не сделать, программа завершится. Затем она отправит трассу исполнения на sys.stderr.

80.1 Исключения. Как работают. Какая иерархия исключений?

Существует довольно большое количество встроенных типов исключений в языке Python, все они составляют определенную иерархию, которая выглядит так, как показано ниже.

BaseException
+– SystemExit
+– KeyboardInterrupt
+– GeneratorExit
+– Exception
 +– StopIteration
 +– StopAsyncIteration
 +– ArithmeticError
 | +– FloatingPointError
 | +– OverflowError
 | +– ZeroDivisionError
 +– AssertionError
 +– AttributeError
 +– BufferError
 +– EOFError
 +– ImportError
 +– ModuleNotFoundError
 +– LookupError
 | +– IndexError
 | +– KeyError
 +– MemoryError
 +– NameError
 | +– UnboundLocalError
 +– OSError
 | +– BlockingIOError
 | +– ChildProcessError
 | +– ConnectionError
 | | +– BrokenPipeError
 | | +– ConnectionAbortedError
 | | +– ConnectionRefusedError
 | | +– ConnectionResetError
 | +– FileExistsError
 | +– FileNotFoundError
 | +– InterruptedError
 | +– IsADirectoryError
 | +– NotADirectoryError
 | +– PermissionError
 | +– ProcessLookupError
 | +– TimeoutError
 +– ReferenceError
 +– RuntimeError
 | +– NotImplementedError
 | +– RecursionError
 +– SyntaxError
 | +– IndentationError
 | +– TabError
 +– SystemError
 +– TypeError
 +– ValueError
 | +– UnicodeError
 | +– UnicodeDecodeError
 | +– UnicodeEncodeError
 | +– UnicodeTranslateError
 +– Warning
 +– DeprecationWarning
 +– PendingDeprecationWarning
 +– RuntimeWarning
 +– SyntaxWarning
 +– UserWarning
 +– FutureWarning
 +– ImportWarning
 +– UnicodeWarning
 +– BytesWarning
 +– ResourceWarning

Как видно из приведенной выше схемы, все исключения являются подклассом исключения BaseException. Более подробно об иерархии исключений и их описании можете прочитать здесь.


81. Как можно преобразовать целое число (integer) в символ Unicode?

Для этого просто нужна встроенная функция chr(x).

82. Если строка (string) начинается с пробела, как его убрать?

Такой пробел можно убрать с помощью метода lstrip().
В этой строке пробелы стояли как в начале, так и в конце. Функция lstrip() убрала крайний слева пробел из строки. Если мы захотим убрать пробел из хвоста, то воспользуемся функцией rstrip().


83. Что за функция enumerate() в Python?

Функция enumerate() осуществляет итерацию вдоль последовательности (sequence), извлекает индекс и его значение.

84. В каком случае while уместнее, чем for?

В целом, for подойдет во всех случаях, когда применим while, однако есть несколько ситуаций, когда с циклом while проще:
Простые повторяющиеся циклы
Когда не нужно осуществлять итерацию вдоль списка элементов (например, записи в базе данных и символы строки.

85. Объясните разницу между полной копией (deep copy) и поверхностной копией (shallow copy).

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


86.1 Можно ли сказать, что массив (array) NumPy лучше списка (list)?

Массивы NumPy имеют три преимущества перед списками:
Они быстрее
Они потребляют меньше памяти
С ними удобнее работать

86.2 Какие отличия между массивом(array) и списком(list) в Python?

Массивы содержат только элементы одинаковых типов данных, то есть тип данных массива должен быть однородным. Массивы потребляют меньше памяти.

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

86.3 Отрицательное значение индексов в Python

Отрицательное значение индексов в Python является популярным использованием slicing (вырезок) коллекций и массивов. То есть индексацией можно пользоваться для создания вырезок из коллекций.

Синтаксис – [start : stop : step]:

  • start– с какого индекса нужно начинать (может быть отрицательным)
  • stop – на каком месте остановится
  • step – количество шагов для перехода. По умолчанию 1.


87. Как можно отслеживать разные версии кода?

Для этого используется контроль версий (version control). Одним из возможных инструментов контроля является Git

Еще: https://blog.volodichev.com/git

87.2 Отличия git merge от git rebase. Слияние веток. Git flow. Как откатить commit. Как решить конфликт в commit. Cherry-pick

Часто у разработчиков возникает выбор между Merge (слияние) и Rebase (перемещение). Git Merge и Git Rebase преследуют одну и ту же цель. Они предназначены для интеграции изменений из одной ветки в другую. Хотя конечная цель одинаковая, принципы работы разные.

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

Rebase(перемещение) — еще один способ перенести изменения из одной ветки в другую. Rebase сжимает все изменения в один «патч». Затем он интегрирует патч в целевую ветку.

Git-flow — альтернативная модель ветвления Git, в которой используются функциональные ветки и несколько основных веток

Cherry-pick В такой ситуации, когда возникает необходимость перенести commit из одной ветки в другую на помощь приходит команда git cherry-pick, применяющая к дереву проекта изменения, которые были внесены указанным каммитом.

88.1 Что такое модули и пакеты в Python?

Модули - это файл или набор файлов Python с расширением <<.py>>, в которых определены и реализованы наборы функций, классов или переменных. Они могут быть импортированы и инициализированы один раз с помощью оператора import. Если требуется частичная функциональность, необходимые классы или функции импортируются с помощью оператора from foo import bar.

Пакет — это каталог с модулями. Пакеты позволяют иерархически структурировать пространство имен модуля с помощью точечной нотации. Как модули помогают избежать столкновений между именами глобальных переменных, так и пакеты помогают избежать столкновений между именами модулей. Создать пакет просто, поскольку он использует присущую системе файловую структуру. Пакет создается как папка в файловой системе и помещается необходимый модуль (файл python). Импорт модуля или его содержимого из пакета требует, чтобы имя пакета был префиксом к имени модуля, соединенным точкой. Подробнее на здесь.

Пакеты и модули – это два механизма, позволяющие осуществлять модульное программирование в Python. Модульное программирование имеет несколько преимуществ:

  • Простота: Работа над одним модулем позволяет сосредоточиться на относительно небольшой части проблемы. Это делает разработку более простой и менее подверженной ошибкам.
  • Удобство обслуживания: Модули предназначены для обеспечения логических границ между различными проблемными областями. Если они написаны таким образом, что уменьшают взаимозависимость, то меньше вероятность того, что изменения в модуле могут повлиять на другие части программы.
  • Возможность повторного использования: Функции, определенные в модуле, могут быть легко использованы повторно в других частях приложения.
  • Разметка: Модули обычно определяют отдельное пространство имен, что помогает избежать путаницы между идентификаторами из других частей программы.

88.2 Можно ли осуществить динамическую загрузку модуля в Python?

При динамической загрузке модули загружаются только когда они становятся нужны. Такой подход — медленный, но он помогает эффективнее использовать память. В Python для этого можно использовать модуль importlib:

89. Какие методы/функции мы используем для определения типа экземпляра (type of instance) и наследования (inheritance)?

Для этого используются type(), isinstance() и issubclass().
1. type() используется для определения типа объекта.
2. isinstance() принимает два аргумента: значение (value) и тип (type). Если значение относится к соответствующему типу, то возвращается True. Если нет, то возвращается False.
3. issubclass() принимает два класса (classes) в качестве аргументов (arguments). Если второй наследует из первого, то возвращается True. Если нет, то возвращается False.


90. Методы (methods) и конструкторы (constructors) — это одно и то же или нет?

Разница между ними очень тонкая, но важная:
Название конструктора должно соответствовать названию класса, а метод можно называть как угодно.
Конструктор исполняется при создании объекта, а метод исполняется при его вызове.
Конструктор исполняется один раз для каждого объекта, а метод можно вызывать по одному объекту неограниченно.
Конструкторы используются для определения (define) и инициализации не статических переменных. Методы используются для осуществления операций в рамках бизнес-логики

91. Что понимается под модулем в питоне?

Модуль — это скрипт, в котором определяются операторы импорта (import statements), функции (functions), классы (classes) и переменные (variables). Файлы ZIP и DLL тоже могут быть модулями. Название модуля хранится в глобальной переменной (global variable) в виде строки (string).


92. Какие в питоне есть модули для работы с файлами?

Питон предлагает следующие библиотеки и модули для обработки текстов и двоичных файлов:
os
os.path
shutil


93. Можете коротко объяснить, как используются модули sqlite3, ctypes, pickle, traceback и itertools.

sqlite3 - помогает обрабатывать базы данных, например SQLite
ctypes - позволяет создавать в питоне типы данных из Си и обрабатывать их
pickle - позволяет переносить любые структуры данных во внешние файлы. Это модуль сериализации и десериализации объектов в Python.
traceback - позволяет извлекать, форматировать и выводить на печать трассы вызовов (stack traces)
itertools - помогает работать с перестановками (permutations), комбинациями (combinations) и другими итерируемыми объектами (iterables).

94. Расскажите про наследование (inheritance) в Python.

Когда один класс наследует из другого, его называют дочерним/производным/подклассом (child/derived/sub class), который наследует из родительского/базового/супер класса (parent/base/super class). Он наследует/получает все атрибуты и методы.
Наследование позволяет повторно использовать код и облегчает создание и дальнейшую работу приложений (applications). В Python поддерживаются следующие виды наследования:
Единичное наследование (Single Inheritance) — класс наследует из одного базового класса.
Множественное наследование (Multiple Inheritance) — класс наследует из двух или нескольких базовых классов.
Многоуровневое наследование (Multilevel Inheritance) — класс наследует из базового класса, который, в свою очередь, наследует из другого базового класса.
Иерархическое наследование (Hierarchical Inheritance) — два класса или несколько классов наследуют из одного базового класса (single base class).
Гибридное наследование (Hybrid Inheritance) — сочетание двух или нескольких видов наследования.


95. Объясните, как в Python осуществляется управление памятью.

В Python объекты и структуры данных (data structures) находятся в закрытой динамически выделяемой области (private heap), которая управляется менеджером памяти Python. Он делегирует часть работы программам распределения ресурсов (allocators), закрепленным за конкретными объектами, и одновременно с этим следит, чтобы они не выходили за пределы динамически выделяемой области. По факту данной областью управляет интерпретатор (interpreter). Пользователь никак не контролирует данный процесс, даже когда манипулирует ссылками объектов на блоки памяти внутри динамической области. Менеджер памяти Python распределяет пространство динамической области среди объектов и другие внутренние буферы по требованию.

В Python оператор присваивания (=) не копирует объекты. Вместо этого он создает связь между существующим объектом и именем целевой переменной. Чтобы создать копии объекта в Python, необходимо использовать модуль copy. Более того, существует два способа создания копий для данного объекта с помощью модуля copy.

  1. Shallow Copy – это побитовая копия объекта. Созданный скопированный объект имеет точную копию значений в исходном объекте. Если одно из значений является ссылкой на другие объекты, копируются только адреса ссылок на них.
  2. Deep Copy – рекурсивно копирует все значения от исходного объекта к целевому, т. е. дублирует даже объекты, на которые ссылается исходный объект.

GC

generational garbage collector — второй алгоритм для очистки объектов на основе поколений[0, 1, 2] и решает проблему с циклическими ссылками.
weakref — слабые ссылки на объекты, которые не препятствуют работе gc


96. Как можно сделать скрипт Python, исполняемый в Unix?

Для этого должны выполняться два условия:
Файл скрипта должен быть в исполняемом режиме.
Первая строка должен начинаться с решетки (хэша, hash(#)), например: #!/usr/local/bin/python

97. Что такое временная подмена (Monkey Patching)?

Она модифицирует класс или модуль во время выполнения (at runtime), то есть представляет собой динамическую модификацию (dynamic modification).


98. Scope в Python – какие бывают?

Объект в Python функционирует в пределах области видимости. Область видимости – это блок кода, в котором объект в Python остается актуальным. Пространства имен уникально идентифицируют все объекты внутри программы. Однако эти пространства имен также имеют определенную для них область видимости, где можно использовать их объекты без префикса. Ниже приведено несколько примеров областей видимости, создаваемых во время выполнения кода в Python:

  • Local scope – относится к локальным объектам, доступным в текущей функции.
  • Global scope – относится к объектам, доступным во время выполнения кода с момента их создания.
  • Module-level scope - относится к глобальным объектам текущего модуля, доступным в программе.
  • Outermost – относится ко всем встроенным именам, вызываемым в программе. Объекты в этой области видимости ищутся в последнюю очередь, чтобы найти имя, на которое ссылаются.

99. Как передаются аргументы – значения или ссылка?

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

По значению: Передается копия реального объекта. Изменение значения копии объекта не приведет к изменению значения исходного объекта.

По ссылке: Передается ссылка на реальный объект. Изменение значения нового объекта изменит значение исходного объекта.

100. Что такое *args и *kwargs?

*args – это специальный синтаксис, используемый в определении функции для передачи аргументов переменной длины.

  • – означает переменную длину, а args – это название принятое в PEP 8, но можно использовать любое другое название

**kwargs – это специальный синтаксис, используемый в определении функции для передачи аргументов переменной длины с ключевыми словами. На самом деле, это dictionary который имеет key и value.

101. В чем разница между func и func()?

func — это представляющий функцию объект, который можно назначить переменной или передать другой функции. Функция func() с круглыми скобками вызывает функцию и возвращает результат.

102. Что такое ORM. Преимущества.

Object-relational mapping(Объектно-реляционное отображение) — прослойка между базой данных и кодом который пишет программист, которая позволяет созданные в программе объекты складывать/получать в/из бд.

  • Один код для любого типа БД
  • Встроенный алгоритм оптимизации запросов
  • ORM избавляет программиста от написания большого количества кода, часто однообразного и подверженного ошибкам, тем самым значительно повышая скорость разработки

103. Что такое Pattern Matching( match case)?

Pattern Matching — механизм для проверки данных, их распаковки и управления потоком выполнения.

   match value:
       case "load":
           load()
       case "save":
           save()
       case _:
           default()

class Switch:
    on = 1
    off = 0
    
status = 0

match status:
    case Switch.on:
        print('On')    
    case Switch.off:
        print('Off')

https://habr.com/ru/post/585216

Алгоритмы и структуры данных

1. Что такое Бинарное дерево. Преимущества.

1.1 Бинарное дерево — это структура данных, в которой каждый узел или вершина имеет не более двух дочерних элементов.

  • Не нужно сравнивать со всеми элементами массива.
  • Строится по мере поступления данных
  • Быстрый обход

1.2 Бинарный поиск — это поиск заданного элемента на упорядоченном множестве, осуществляемый путем неоднократного деления этого множества на две части таким образом, что искомый элемент попадает в одну из этих частей.

REST и Api

1. Что такое CRUD?

ыы

2. Что такое Идемпотентность?

Идемпотентность(лат. idem — тот же самый + potens — способный) — свойство объекта или операции при повторном применении операции к объекту давать тот же результат, что и при первом. Термин предложил американский математик Бенджамин Пирс (англ. Benjamin Peirce) в статьях 1870-х годов.

Django

1. Каков жизненный цикл запросов Django?

  • . Когда пользователь вводит URL-адрес в браузере, браузер генерирует заголовок запроса и тело запроса и отправляет его на сервер.
    Заголовок и тело запроса будут содержать действие (действие) браузера, которым обычно является получение или публикация, которое отражено в URL-адресе.
  • URL-адрес проходит через wsgi в Django, затем проходит через промежуточное ПО Django, и, наконец, URL-адрес проходит через таблицу сопоставления маршрутизации и совпадает по одному в маршруте.
    После успешного совпадения одного из совпадений выполняется соответствующая функция просмотра, и последующие маршруты больше не будут соответствовать.
  • Функция просмотра запрашивает соответствующие данные в соответствии с запросом клиента. Вернитесь в Django, а затем Django вернет клиенту данные, которые хочет клиент, в виде строки.
  • Клиентский браузер получает возвращенные данные и отображает их пользователю после рендеринга.

Fastapi

1. 123

SQLalchemy

  1. Как получать join данные(lazy)

SQL

1. Что такое JOIN. Какие виды бывают?

JOIN — оператор языка SQL, который является реализацией операции соединения реляционной алгебры. Входит в предложение FROM операторов SELECT, UPDATE и DELETE.

INNER JOIN(по умолчанию) Оператор внутреннего соединения INNER JOIN соединяет две таблицы. Порядок таблиц для оператора неважен, поскольку оператор является коммутативным

OUTER JOIN — Соединение двух таблиц, в результат которого обязательно входят все строки либо одной, либо обеих таблиц.

LEFT OUTER JOIN — Оператор левого внешнего соединения LEFT OUTER JOIN соединяет две таблицы. Порядок таблиц для оператора важен, поскольку оператор не является коммутативным.

RIGHT OUTER JOIN Оператор правого внешнего соединения RIGHT OUTER JOIN соединяет две таблицы. Порядок таблиц для оператора важен, поскольку оператор не является коммутативным.

FULL OUTER JOIN — Оператор полного внешнего соединения FULL OUTER JOIN соединяет две таблицы. Порядок таблиц для оператора неважен, поскольку оператор является коммутативным.

CROSS JOIN Оператор перекрёстного соединения, или декартова произведения CROSS JOIN соединяет две таблицы. Порядок таблиц для оператора неважен, поскольку оператор является коммутативным.

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

2. Что такое SQL?

SQL расшифровывается как «Structured Query Language» — «язык структурированных запросов». Этот язык используется для взаимодействия с базами данных. Согласно ANSI (Американский национальный институт стандартов) SQL является стандартным языком запросов для систем управления реляционными базами данных и используется для поддержки этих баз и различных манипуляций с данными. В общем, это язык, используемый для создания и удаления баз данных, выборки и изменения строк таблиц и множества других операций.

3. Поясните, в чем разница между выражениями HAVING и WHERE