Python | Вопросы собесов
Сайт: https://easyoffer.ru/ Все каналы: t.me/+xGeAw6ckJ4liYzQy Контакт для рекламы: @sendme_ads
Show more📈 Analytical overview of Telegram channel Python | Вопросы собесов
Channel Python | Вопросы собесов (@python_easy_ru) in the Russian language segment is an active participant. Currently, the community unites 12 669 subscribers, ranking 9 607 in the Technologies & Applications category and 50 557 in the Russia region.
📊 Audience metrics and dynamics
Since its creation on невідомо, the project has demonstrated rapid growth, gathering an audience of 12 669 subscribers.
According to the latest data from 06 October, 2026, the channel demonstrates stable activity. Although there has been a change in the number of participants by -104 over the last 30 days and by -7 over the last 24 hours, overall reach remains high.
- Verification status: Not verified
- Engagement rate (ER): The average audience engagement rate is 5.88%. Within the first 24 hours after publication, content typically collects 4.27% reactions from the total number of subscribers.
- Post reach: On average, each post receives 745 views. Within the first day, a publication typically gains 541 views.
- Reactions and interaction: The audience actively supports content: the average number of reactions per post is 2.
- Thematic interests: Content is focused on key topics such as ставь, модуль, строка, docker, alice.
📝 Description and content policy
The author describes the resource as a platform for expressing subjective opinions:
“Сайт: https://easyoffer.ru/
Все каналы: t.me/+xGeAw6ckJ4liYzQy
Контакт для рекламы: @sendme_ads”
Thanks to the high frequency of updates (latest data received on 07 October, 2026), the channel maintains relevance and a high level of publication reach. Analytics show that the audience actively interacts with content, making it an important point of influence in the Technologies & Applications category.
asyncio) в Python не выполняет код параллельно, а переключается между задачами во время ожидания (I/O-bound).
Если в async-функции делать тяжёлые вычисления (CPU-bound), это блокирует asyncio, потому что в Python есть GIL (Global Interpreter Lock).
🚩Асинхронность в Python подходит для ввода-вывода (I/O-bound)
Асинхронность позволяет выполнять задачи без блокировки, но только если они ждут чего-то (файлы, сеть, БД).
import asyncio
import aiohttp
async def fetch(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.text()
async def main():
urls = ["https://example.com"] * 5
results = await asyncio.gather(*(fetch(url) for url in urls))
asyncio.run(main())
🚩Проблема с `async` и тяжёлыми вычислениями (CPU-bound)
Если в async-функции делать тяжёлые вычисления, Python не сможет переключаться между задачами.
import asyncio
async def heavy_task(n):
print(f"Вычисляю {n}...")
total = sum(i**2 for i in range(n)) # Долгий процесс
return total
async def main():
await asyncio.gather(heavy_task(10**7), heavy_task(10**7))
asyncio.run(main())
🚩Как правильно выполнять вычисления в `async`?
🟠Использовать `asyncio.to_thread()` (делегирование в потоки)
В Python 3.9+ можно выполнять CPU-задачи в отдельных потоках, не блокируя asyncio.
import asyncio
def heavy_computation(n):
return sum(i**2 for i in range(n))
async def main():
result = await asyncio.to_thread(heavy_computation, 10**7)
print(result)
asyncio.run(main())
🟠Использовать `multiprocessing` (запуск на нескольких ядрах)
Так как Python использует GIL, единственный способ выполнять настоящий параллелизм — это multiprocessing.
import asyncio
import multiprocessing
def heavy_computation(n):
return sum(i**2 for i in range(n))
async def main():
loop = asyncio.get_running_loop()
with multiprocessing.Pool() as pool:
result = await loop.run_in_executor(pool, heavy_computation, 10**7)
print(result)
asyncio.run(main())
Ставь 👍 и забирай 📚 Базу знаний?id=123).
🟠Поиск ресурса
находит запрашиваемый файл, данные из базы или другой ресурс.
🟠Возврат ответа
отправляет данные клиенту (если ресурс найден — код 200, если нет — 404).
🚩Особенности GET-запроса
🟠Безопасный
не изменяет данные на сервере, используется только для чтения.
🟠Идемпотентный
повторные запросы дают одинаковый результат.
🟠Параметры в URL
данные передаются через строку запроса, что не подходит для конфиденциальной информации.
import requests
response = requests.get("https://api.example.com/data", params={"id": 123})
print(response.text) # Данные с сервера
Ставь 👍 и забирай 📚 Базу знанийCREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(50) NOT NULL -- Поле name обязательно
);
Нельзя вставить NULL в name
INSERT INTO users (id, name) VALUES (1, NULL); -- Ошибка!
🚩`UNIQUE` (Гарантирует уникальность значений)
Запрещает дубликаты в столбце
CREATE TABLE users (
id INT PRIMARY KEY,
email VARCHAR(100) UNIQUE -- Email должен быть уникальным
);
Попытка вставить одинаковый email вызовет ошибку
INSERT INTO users (id, email) VALUES (1, 'test@example.com');
INSERT INTO users (id, email) VALUES (2, 'test@example.com'); -- Ошибка!
Создание UNIQUE на нескольких колонках
CREATE TABLE orders (
user_id INT,
product_id INT,
UNIQUE (user_id, product_id) -- Запрещает заказывать один товар дважды
);
🚩`PRIMARY KEY` (Главный ключ, уникальный идентификатор)
Объединяет NOT NULL + UNIQUE и гарантирует, что строка уникальна.
CREATE TABLE users (
id INT PRIMARY KEY, -- Уникальный идентификатор
name VARCHAR(50)
);
Можно создать PRIMARY KEY на нескольких колонках
CREATE TABLE enrollments (
student_id INT,
course_id INT,
PRIMARY KEY (student_id, course_id) -- Один студент не может записаться дважды на один курс
);
🚩`FOREIGN KEY` (Связь таблиц)
Создаёт связь между таблицами и поддерживает ссылочную целостность.
Есть таблица пользователей (users) и таблица заказов (orders), где user_id в orders должен ссылаться на id в users.
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(50)
);
CREATE TABLE orders (
id INT PRIMARY KEY,
user_id INT,
FOREIGN KEY (user_id) REFERENCES users(id) -- Связь с таблицей users
);
Что делать при удалении пользователя?
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
Ставь 👍 и забирай 📚 Базу знанийimport sys
print(sys.getrecursionlimit()) # 1000 (обычное значение)
Если превысить этот лимит, программа вызовет ошибку
def recursive():
return recursive()
recursive() # RecursionError: maximum recursion depth exceeded
🚩Как изменить лимит?
Можно увеличить глубину рекурсии, но это небезопасно
sys.setrecursionlimit(2000) # Увеличиваем до 2000
🟠Рекурсия требует много памяти
Каждый рекурсивный вызов создаёт новый фрейм в стеке вызовов.
def factorial(n):
if n == 1:
return 1
return n * factorial(n - 1)
print(factorial(10000)) # Ошибка из-за переполнения стека
🟠Отсутствие оптимизации хвостовой рекурсии
Другие языки (например, Lisp, JavaScript) автоматически оптимизируют хвостовую рекурсию (Tail Call Optimization, TCO).
Python не делает этого, поэтому даже "идеальная" рекурсия всё равно переполняет стек.
def tail_recursive(n, acc=1):
if n == 1:
return acc
return tail_recursive(n - 1, n * acc)
print(tail_recursive(1000)) # Всё равно вызовет RecursionError
🟠Рекурсия медленнее цикла
Рекурсивный вызов требует больше накладных расходов (создание стек-фреймов), чем обычный for или while.
# Итеративный вариант (быстрее)
def factorial_iter(n):
result = 1
for i in range(1, n + 1):
result *= i
return result
# Рекурсивный вариант (медленнее)
def factorial_rec(n):
if n == 1:
return 1
return n * factorial_rec(n - 1)
Ставь 👍 и забирай 📚 Базу знанийupdate_fields в методе .save().
🚩Как использовать `update_fields`
Пример модели
from django.db import models
class UserProfile(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField()
age = models.IntegerField()
Обновляем только поле name, не трогая email и age
user = UserProfile.objects.get(id=1)
user.name = "Новый пользователь"
user.save(update_fields=["name"]) # Обновит только поле `name`
🚩Что делает `update_fields`?
Генерирует SQL-запрос только для указанных полей, например:
UPDATE user_profile SET name = 'Новый пользователь' WHERE id = 1;
🚩Когда `update_fields` полезен?
Уменьшает нагрузку на БД, так как обновляет только нужные поля.
Полезен, если нужно изменить одно поле, а не всю запись.
Избегает ненужных изменений в auto_now и auto_now_add полях (DateTimeField).
🚩Ограничения `update_fields`
Нельзя использовать при создании объекта (save() с update_fields не работает для .create()).
user = UserProfile(name="Alice", email="alice@example.com")
user.save(update_fields=["name"]) # ❌ Ошибка, объект ещё не в базе!
Не обновляет auto_now-поля (DateTimeField) автоматически!
updated_at = models.DateTimeField(auto_now=True) # Не обновится с `update_fields`
Решение: обновить вручную:
user.updated_at = timezone.now()
user.save(update_fields=["name", "updated_at"])
Ставь 👍 и забирай 📚 Базу знанийx = 10
print(id(x)) # 140735598722544 (адрес в памяти)
x = x + 5 # Создаётся новый объект!
print(id(x)) # 140735598722704 (новый адрес)
Пример: str неизменяемая
s = "hello"
print(id(s)) # 140735598723664
s = s + " world" # Создаётся новая строка!
print(id(s)) # 140735598724240 (новый адрес)
🚩Изменяемые (`mutable`) типы
Можно менять их содержимое без создания нового объекта.
lst = [1, 2, 3]
print(id(lst)) # 140735598722544
lst.append(4) # Изменяем список
print(id(lst)) # 140735598722544 (адрес остался тот же!)
Пример: dict изменяемый
d = {"name": "Alice"}
print(id(d)) # 140735598723664
d["age"] = 25 # Добавляем ключ
print(id(d)) # 140735598723664 (адрес не изменился!)
🚩Почему это важно?
Неизменяемые объекты безопаснее для ключей dict и set
d = {}
d[[1, 2, 3]] = "Ошибка!" # ❌ TypeError: unhashable type: 'list'
Используем tuple вместо list (он неизменяемый)
d[(1, 2, 3)] = "OK"
Ошибки с изменяемыми значениями по умолчанию
def add_item(lst=[]): # ❌ Опасный код!
lst.append(1)
return lst
print(add_item()) # [1]
print(add_item()) # [1, 1] ❌ Список не создаётся заново!
Используем None вместо списка
def add_item(lst=None):
if lst is None:
lst = []
lst.append(1)
return lst
🚩Копирование объектов (`copy()` vs `deepcopy()`)
copy() делает поверхностную копию (новый объект, но старые вложенные элементы).
deepcopy() делает глубокую копию (всё новое).
import copy
lst1 = [[1, 2, 3], [4, 5, 6]]
lst2 = copy.copy(lst1) # Поверхностная копия
lst2[0][0] = 99
print(lst1) # [[99, 2, 3], [4, 5, 6]] ❌ Исходный список изменился!
Используем deepcopy() для полной независимой копии
lst3 = copy.deepcopy(lst1)
lst3[0][0] = 100
print(lst1) # [[99, 2, 3], [4, 5, 6]] ✅ Не изменился!
Ставь 👍 и забирай 📚 Базу знаний