Python | Вопросы собесов
Cайт: easyoffer.ru Реклама: @easyoffer_adv ВП: @easyoffer_vp Тесты t.me/+20tRfhrwPpM4NDQy Задачи t.me/+nsl4meWmhfQwNDVi Вакансии t.me/+cXGKkrOY2-w3ZTky
Показати більше📈 Аналітичний огляд Telegram-каналу Python | Вопросы собесов
Канал Python | Вопросы собесов (@python_easy_ru) у мовному сегменті Російська є активним учасником. На даний момент спільнота об'єднує 13 110 підписників, посідаючи 9 732 місце в категорії Технології та додатки та 50 668 місце у регіоні Росія.
📊 Показники аудиторії та динаміка
З моменту свого створення невідомо, проект продемонстрував стрімке зростання, зібравши аудиторію у 13 110 підписників.
За останніми даними від 05 червня, 2026, канал демонструє стабільну активність. Хоча за останні 30 днів спостерігається зміна кількості учасників на -48, а за останні 24 години на -5, загальне охоплення залишається високим.
- Статус верифікації: Не верифікований
- Рівень залученості (ER): Середній показник залученості аудиторії становить 6.21%. Протягом перших 24 годин після публікації контент зазвичай збирає 6.02% реакцій від загальної кількості підписників.
- Охоплення публікацій: В середньому кожен допис отримує 814 переглядів. Протягом першої доби публікація в середньому набирає 789 переглядів.
- Реакції та взаємодія: Аудиторія активно підтримує контент: середня кількість реакцій на один пост – 4.
- Тематичні інтереси: Контент зосереджений навколо ключових тем, таких як ставь, модуль, строка, docker, alice.
📝 Опис та контентна політика
Автор описує ресурс як майданчик для висловлення суб'єктивної думки:
“Cайт: easyoffer.ru
Реклама: @easyoffer_adv
ВП: @easyoffer_vp
Тесты t.me/+20tRfhrwPpM4NDQy
Задачи t.me/+nsl4meWmhfQwNDVi
Вакансии t.me/+cXGKkrOY2-w3ZTky”
Завдяки високій частоті оновлень (останні дані отримано 07 червня, 2026), канал підтримує актуальність та високий рівень охоплення публікацій. Аналітика показує, що аудиторія активно взаємодіє з контентом, що робить його важливою точкою впливу в категорії Технології та додатки.
x = "глобальная" # Global
def outer():
x = "охватывающая" # Enclosing
def inner():
x = "локальная" # Local
print(x) # Поиск начинается отсюда (L)
inner()
outer()
Вывод
локальная🚩Глобальные переменные (`global`) Если нужно изменить глобальную переменную внутри функции, используем
global
x = 10 # Глобальная переменная
def modify_global():
global x
x = 20 # Меняем глобальную переменную
modify_global()
print(x) # 20
🚩Переменные из внешней функции (`nonlocal`)
Если в вложенной функции нужно изменить переменную из enclosing-области, используем nonlocal
def outer():
x = 10 # Переменная из enclosing-области
def inner():
nonlocal x
x = 20 # Меняем `x` в `outer()`
inner()
print(x) # 20
outer()
🚩Что если переменная отсутствует во всех областях?
Если переменная не найдена в LEGB, Python выдаст NameError
def func():
print(y) # Ошибка: y не объявлена!
func()
Ошибка
NameError: name 'y' is not defined🚩`Built-in` — встроенные функции Python в последнюю очереде проверяет встроенные функции (
print(), len(), sum() и т. д.).
print = "Ошибка!" # Переопределили встроенную функцию
print("Hello") # TypeError: 'str' object is not callable
Ставь 👍 и забирай 📚 Базу знаний@ используется для декораторов, и разница между @foobar и @foobar() заключается в том, вызывается ли сам декоратор с параметрами или без.
🟠`@foobar` — декоратор без вызова
Если мы пишем @foobar, то используется сам декоратор как есть, без передачи аргументов.
def foobar(func):
def wrapper():
print("Декоратор вызван!")
return func()
return wrapper
@foobar # Просто передаём функцию в декоратор
def hello():
print("Hello, world!")
hello()
Вывод
Декоратор вызван! Hello, world!🟠`@foobar()` — декоратор с вызовом (и параметрами) Если декоратор принимает параметры, то он сначала вызывается (
foobar()), а потом возвращает сам декоратор.
def foobar(arg):
def decorator(func):
def wrapper():
print(f"Декоратор вызван с аргументом: {arg}")
return func()
return wrapper
return decorator
@foobar("Привет") # Вызываем foobar("Привет"), который вернёт реальный декоратор
def hello():
print("Hello, world!")
hello()
Вывод
Декоратор вызван с аргументом: Привет Hello, world!Ставь 👍 и забирай 📚 Базу знаний
threading, но из-за GIL (Global Interpreter Lock) потоки не могут выполняться параллельно на нескольких ядрах.
🟠Модуль `threading` (многопоточность, но с GIL)
Модуль threading позволяет запускать несколько потоков (threads) в одном процессе.
import threading
import time
def task(name):
print(f"{name} начал работу")
time.sleep(2) # Имитация задержки
print(f"{name} завершил работу")
# Создаём два потока
t1 = threading.Thread(target=task, args=("Поток 1",))
t2 = threading.Thread(target=task, args=("Поток 2",))
t1.start()
t2.start()
t1.join()
t2.join()
print("Все потоки завершены")
Вывод
Поток 1 начал работу Поток 2 начал работу (пауза 2 секунды) Поток 1 завершил работу Поток 2 завершил работу Все потоки завершены🟠Модуль `multiprocessing` (настоящая параллельность) В отличие от
threading, модуль multiprocessing создаёт отдельные процессы, которые могут выполняться на разных ядрах процессора.
import multiprocessing
import time
def task(name):
print(f"{name} начал работу")
time.sleep(2)
print(f"{name} завершил работу")
if __name__ == "__main__":
p1 = multiprocessing.Process(target=task, args=("Процесс 1",))
p2 = multiprocessing.Process(target=task, args=("Процесс 2",))
p1.start()
p2.start()
p1.join()
p2.join()
print("Все процессы завершены")
🟠Модуль `concurrent.futures` (более удобный API)
Этот модуль позволяет легко управлять потоками (ThreadPoolExecutor) и процессами (ProcessPoolExecutor).
from concurrent.futures import ThreadPoolExecutor
import time
def task(n):
time.sleep(2)
return f"Готово: {n}"
with ThreadPoolExecutor(max_workers=2) as executor:
results = executor.map(task, [1, 2, 3])
for result in results:
print(result)
Пример ProcessPoolExecutor (процессы)
from concurrent.futures import ProcessPoolExecutor
def square(n):
return n * n
with ProcessPoolExecutor() as executor:
results = executor.map(square, [1, 2, 3, 4])
print(list(results)) # [1, 4, 9, 16]
🟠Модуль `asyncio` (асинхронность, не потоки!)
Модуль asyncio не создаёт потоки или процессы, а работает через "корутины" и цикл событий (event loop).
import asyncio
async def task():
print("Начало")
await asyncio.sleep(2) # Не блокирует другие задачи
print("Конец")
async def main():
await asyncio.gather(task(), task())
asyncio.run(main())
Ставь 👍 и забирай 📚 Базу знанийdict.
🚩Основная идея
Ключ проходит через хеш-функцию → превращается в число (индекс).
Значение сохраняется в массиве по этому индексу.
При поиске: ключ снова хешируется, и мы мгновенно находим нужное значение.
🚩Как это работает в Python?
Создание хеш-таблицы (dict)
hash_map = {} # Пустой словарь
hash_map["apple"] = 10 # Добавляем элемент
hash_map["banana"] = 20
print(hash_map["apple"]) # 10
🟠Хеширование ключа
Ключи сначала хешируются с помощью встроенной функции hash().
print(hash("apple")) # Например: 2837462816
print(hash("banana")) # Другое число
🟠Разрешение коллизий
Иногда разные ключи могут давать одинаковый хеш. Это называется коллизией. Python использует метод цепочек (Chaining): Если у двух ключей один хеш, они хранятся в виде списка в одной ячейке.
hash_map = { "key1": 100, "key2": 200 }
print(hash("key1") % 10) # Допустим, 4
print(hash("key2") % 10) # Тоже 4 (коллизия!)
# Python хранит их в одной ячейке как список [(key1, 100), (key2, 200)]
🟠Динамическое расширение
При заполнении хеш-таблицы, если она становится слишком загруженной, Python автоматически увеличивает её размер, чтобы избежать замедления.
d = {} # Создаём пустой dict
for i in range(1000):
d[i] = i
print(len(d)) # 1000, Python сам расширил таблицу
🟠Удаление элементов
Удаление также выполняется за O(1)
del hash_map["apple"] # Мгновенно удаляем
Ставь 👍 и забирай 📚 Базу знанийfrom abc import ABC, abstractmethod
# Интерфейс стратегии
class Strategy(ABC):
@abstractmethod
def sort(self, data):
pass
# Конкретные стратегии
class BubbleSortStrategy(Strategy):
def sort(self, data):
print("Sorting using Bubble Sort")
for i in range(len(data)):
for j in range(0, len(data)-i-1):
if data[j] > data[j+1]:
data[j], data[j+1] = data[j+1], data[j]
class QuickSortStrategy(Strategy):
def sort(self, data):
print("Sorting using Quick Sort")
self.quick_sort(data, 0, len(data) - 1)
def quick_sort(self, data, low, high):
if low < high:
pi = self.partition(data, low, high)
self.quick_sort(data, low, pi - 1)
self.quick_sort(data, pi + 1, high)
def partition(self, data, low, high):
pivot = data[high]
i = low - 1
for j in range(low, high):
if data[j] <= pivot:
i = i + 1
data[i], data[j] = data[j], data[i]
data[i + 1], data[high] = data[high], data[i + 1]
return i + 1
# Контекст
class SortingContext:
def __init__(self, strategy: Strategy):
self._strategy = strategy
def set_strategy(self, strategy: Strategy):
self._strategy = strategy
def sort(self, data):
self._strategy.sort(data)
# Клиентский код
data = [5, 2, 9, 1, 5, 6]
context = SortingContext(BubbleSortStrategy())
context.sort(data)
print(data) # [1, 2, 5, 5, 6, 9]
context.set_strategy(QuickSortStrategy())
data = [3, 7, 8, 5, 2, 1, 9, 5, 4]
context.sort(data)
print(data) # [1, 2, 3, 4, 5, 5, 7, 8, 9]
🚩Плюсы и минусы
➕Изоляция алгоритмов
Алгоритмы инкапсулируются в отдельные классы, что упрощает их замену и добавление.
➕Упрощение кода
Контекст использует стратегии, избегая громоздких условных операторов.
➕Гибкость и расширяемость
Легко добавлять новые стратегии без изменения существующего кода.
➖Усложнение структуры кода
Добавление множества классов стратегий может усложнить проект.
➖Контекст знает о стратегиях
Контекст должен знать о всех возможных стратегиях, чтобы иметь возможность их переключать.
🚩Когда использовать данный паттерн?
Когда есть несколько вариантов алгоритмов для выполнения задачи.
Когда нужно динамически выбирать алгоритм во время выполнения.
Когда необходимо избежать множества условных операторов для выбора алгоритма.
Ставь 👍 и забирай 📚 Базу знанийdatetime позволяет работать с датами и временем, но по умолчанию он не поддерживает часовые пояса.
from datetime import datetime
dt = datetime.now() # Получаем текущую дату и время
print(dt) # Например: 2024-02-28 14:30:00.123456
print(dt.tzinfo) # None (нет информации о часовом поясе)
🟠`pytz` – внешний модуль для работы с часовыми поясами
Библиотека pytz добавляет поддержку часовых поясов и позволяет работать с разными временными зонами.
from datetime import datetime
import pytz
tz = pytz.timezone("Europe/Moscow") # Часовой пояс Москвы
dt = datetime.now(tz) # Получаем текущее время с учетом часового пояса
print(dt) # Например: 2024-02-28 17:30:00+03:00
print(dt.tzinfo) # Europe/Moscow
🚩Как работать с часовыми поясами правильно?
Создание datetime с часовым поясом pytz
dt = datetime(2024, 2, 28, 15, 0) # Наивная дата
tz = pytz.timezone("Europe/Moscow")
dt = tz.localize(dt) # Присваиваем часовой пояс
print(dt) # 2024-02-28 15:00:00+03:00
Конвертация времени между часовыми поясами
ny_tz = pytz.timezone("America/New_York")
ny_time = dt.astimezone(ny_tz)
print(ny_time) # Конвертированное время в Нью-Йорке
Использование UTC (лучший подход для серверов)
utc_now = datetime.now(pytz.UTC) # Текущее время в UTC
print(utc_now) # Например: 2024-02-28 14:30:00+00:00
Ставь 👍 и забирай 📚 Базу знаний
Вже доступно! Дослідження Telegram за 2025 — головні інсайти року 
