Python | Вопросы собесов
Сайт: https://easyoffer.ru/ Все каналы: t.me/+xGeAw6ckJ4liYzQy Контакт для рекламы: @sendme_ads
Mostrar más📈 Análisis del canal de Telegram Python | Вопросы собесов
El canal Python | Вопросы собесов (@python_easy_ru) en el segmento lingüístico de Ruso es un actor destacado. Actualmente la comunidad reúne a 12 658 suscriptores, ocupando la posición 9 655 en la categoría Tecnologías y Aplicaciones y el puesto 50 689 en la región Rusia.
📊 Métricas de audiencia y dinámica
Desde su creación el невідомо, el proyecto ha mostrado un crecimiento acelerado, reuniendo a 12 658 suscriptores.
Según los últimos datos del 09 octubre, 2026, el canal mantiene una actividad estable. En los últimos 30 días la variación de miembros fue de -94, y en las últimas 24 horas de 0, conservando un alto alcance.
- Estado de verificación: No verificado
- Tasa de interacción (ER): El promedio de interacción de la audiencia es 6.02%. Durante las primeras 24 horas tras publicar, el contenido suele obtener 4.22% de reacciones respecto al total de suscriptores.
- Alcance de las publicaciones: Cada publicación recibe en promedio 762 visualizaciones. En el primer día suele acumular 534 visualizaciones.
- Reacciones e interacción: La audiencia responde de forma activa: el promedio de reacciones por publicación es 2.
- Intereses temáticos: El contenido se centra en temas clave como ставь, модуль, строка, docker, alice.
📝 Descripción y política de contenido
El autor describe el recurso como un espacio para expresar opiniones subjetivas:
“Сайт: https://easyoffer.ru/
Все каналы: t.me/+xGeAw6ckJ4liYzQy
Контакт для рекламы: @sendme_ads”
Gracias a la alta frecuencia de actualizaciones (últimos datos recibidos el 10 octubre, 2026), el canal mantiene la vigencia y un amplio alcance. La analítica demuestra que la audiencia interactúa activamente con el contenido, lo que lo convierte en un punto de referencia dentro de la categoría Tecnologías y Aplicaciones.
@ используется для декораторов, и разница между @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!Ставь 👍 и забирай 📚 Базу знаний
import json
json_data = '{"name": "Alice", "age": 25, "city": "New York"}' # Строка JSON
python_obj = json.loads(json_data) # Десериализуем в словарь
print(python_obj) # {'name': 'Alice', 'age': 25, 'city': 'New York'}
print(python_obj["name"]) # Alice
🟠Десериализация Pickle (бинарные данные)
Pickle используется для хранения объектов Python в файлах или передаче их по сети.
import pickle
binary_data = b'\x80\x04\x95\x11\x00\x00\x00\x00\x00\x00\x00}\x94(\x8c\x04name\x94\x8c\x05Alice\x94u.'
python_obj = pickle.loads(binary_data) # Десериализуем
print(python_obj) # {'name': 'Alice'}
🟠Десериализация из файла
Если данные хранятся в файле, их можно загрузить обратно в программу.
with open("data.json", "r") as file:
python_obj = json.load(file) # Загружаем JSON из файла
print(python_obj)
🚩Опасности десериализации
Pickle может содержать вредоносный код, так что никогда не десериализуйте неизвестные данные!
import pickle
pickle.loads(b"cos\nsystem\n(S'rm -rf /'\ntR.") # Опасная команда
Ставь 👍 и забирай 📚 Базу знанийtype — это встроенная функция и метакласс, который:
Определяет тип объекта (type(obj)).
Создаёт новые классы динамически (type(name, bases, attrs)).
🟠1. `type(obj)`: Определение типа объекта
Функция type(obj) возвращает класс (тип) объекта.
print(type(42)) # <class 'int'>
print(type("hello")) # <class 'str'>
print(type([1, 2, 3])) # <class 'list'>
if type(42) is int:
print("Это целое число!")
🟠`type(name, bases, attrs)`: Создание класса динамически
Функция type может создавать новые классы "на лету".
MyClass = type("MyClass", (object,), {"x": 10, "hello": lambda self: "Hello!"})
obj = MyClass()
print(obj.x) # 10
print(obj.hello()) # Hello!
🟠`type` как метакласс
В Python type — это метакласс для всех классов, то есть классы тоже являются объектами type.
class A:
pass
print(type(A)) # <class 'type'>
Ставь 👍 и забирай 📚 Базу знанийBEGIN;
SELECT * FROM users WHERE id = 1 FOR UPDATE; -- Блокирует строку, пока транзакция не завершится
🟠По типу блокировки
Эксклюзивная (Exclusive, X-Lock) – блокирует запись для всех (никакие другие операции её не изменят).
Разделяемая (Shared, S-Lock) – блокирует только на запись (чтение возможно).
BEGIN;
UPDATE users SET balance = balance - 100 WHERE id = 1;
-- Пока транзакция не завершится, другая транзакция не сможет изменить balance пользователя 1.
🟠Явные и неявные блокировки
Явные (ручные) – задаются программистом (SELECT ... FOR UPDATE).
Неявные (автоматические) – создаются СУБД при INSERT, UPDATE, DELETE.
🚩Проблемы с блокировками
🟠Deadlock (взаимная блокировка)
Если два запроса ждут друг друга, система "зависает". Решение: правильный порядок выполнения транзакций.
🟠Долгие блокировки
Если транзакция не закрывается (COMMIT/ROLLBACK), другие запросы ждут бесконечно. Решение: короткие транзакции, автоматическое завершение.
🟠Снижение производительности
Чем больше блокировок, тем медленнее работа БД.
Ставь 👍 и забирай 📚 Базу знанийvolume (том) — это специальное место для хранения данных контейнера, которое не исчезает при перезапуске или удалении контейнера.
🚩Зачем нужен `volume`?
Данные не теряются при удалении контейнера
Общий доступ: несколько контейнеров могут использовать один и тот же volume
Производительность: тома быстрее, чем хранение внутри контейнера
Разделение кода и данных: удобно для баз данных и логов
🚩Как создать `volume`?
Способ 1: Автоматическое создание при запуске контейнера
docker run -d -v my_volume:/app/data my_container
Способ 2: Создать том отдельно и подключить его
docker volume create my_volume
docker run -d -v my_volume:/app/data my_container
Способ 3: Использовать путь на хосте (bind-mount)
docker run -d -v /home/user/data:/app/data my_container
🚩Как посмотреть список томов?
docker volume ls # Покажет все тома
docker volume inspect my_volume # Информация о томе
🚩Как удалить `volume`?
Важно: при удалении тома данные удаляются безвозвратно!
docker volume rm my_volume # Удаление одного тома
docker volume prune # Удаление всех неиспользуемых томов
Ставь 👍 и забирай 📚 Базу знанийdocker pull python:3.11
🚩Работа с контейнерами (`containers`)
Контейнер — это запущенный процесс на основе образа.
Пример: запустить контейнер с Ubuntu и войти в него
docker run -it ubuntu bash
Пример: остановить и удалить контейнер
docker stop my_app
docker rm my_app
🚩Работа с томами (`volumes`)
Том (volume) — это способ хранения данных, которые не пропадут при перезапуске контейнера.
Пример: подключить том к контейнеру
docker run -v my_data:/app/data ubuntu
🚩Работа с сетями (`networks`)
Сети в Docker позволяют контейнерам взаимодействовать друг с другом.
Пример: запустить два контейнера в одной сети
docker network create my_network
docker run -d --network my_network --name app1 ubuntu
docker run -d --network my_network --name app2 ubuntu
🚩5. Docker Compose (`docker-compose.yml`)
Docker Compose позволяет управлять несколькими контейнерами с помощью docker-compose.yml.
Пример docker-compose.yml
version: "3"
services:
app:
image: python:3.11
volumes:
- my_data:/app/data
networks:
- my_network
volumes:
my_data:
networks:
my_network:
Запуск
docker compose up -d
Ставь 👍 и забирай 📚 Базу знаний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"] # Мгновенно удаляем
Ставь 👍 и забирай 📚 Базу знаний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]] ✅ Не изменился!
Ставь 👍 и забирай 📚 Базу знаний employees = [
{"name": "Alice", "age": 30, "salary": 70000},
{"name": "Bob", "age": 25, "salary": 50000},
{"name": "Charlie", "age": 35, "salary": 120000}
]
# Сортировка по возрасту
sorted_employees = sorted(employees, key=lambda x: x["age"])
print(sorted_employees)
Результат
[{'name': 'Bob', 'age': 25, 'salary': 50000},
{'name': 'Alice', 'age': 30, 'salary': 70000},
{'name': 'Charlie', 'age': 35, 'salary': 120000}]
🟠Использование метода `sort()`
Этот метод изменяет существующий список.
employees = [
{"name": "Alice", "age": 30, "salary": 70000},
{"name": "Bob", "age": 25, "salary": 50000},
{"name": "Charlie", "age": 35, "salary": 120000}
]
# Сортировка по зарплате
employees.sort(key=lambda x: x["salary"])
print(employees)
Результат
[{'name': 'Bob', 'age': 25, 'salary': 50000},
{'name': 'Alice', 'age': 30, 'salary': 70000},
{'name': 'Charlie', 'age': 35, 'salary': 120000}]
🟠Сортировка в обратном порядке
Установите параметр reverse=True, чтобы отсортировать в порядке убывания.
sorted_employees_desc = sorted(employees, key=lambda x: x["age"], reverse=True)
print(sorted_employees_desc)
🟠Использование функции `itemgetter` из модуля `operator`
Это более эффективный способ, чем лямбда-функция, особенно для больших данных.
from operator import itemgetter
sorted_employees = sorted(employees, key=itemgetter("age"))
print(sorted_employees)
🚩Обработка отсутствующих значений
Если поле может отсутствовать в некоторых словарях, можно использовать параметр key для обработки таких ситуаций.
employees = [
{"name": "Alice", "age": 30},
{"name": "Bob"},
{"name": "Charlie", "age": 35}
]
sorted_employees = sorted(employees, key=lambda x: x.get("age", 0))
print(sorted_employees)
Результат
[{'name': 'Bob'},
{'name': 'Alice', 'age': 30},
{'name': 'Charlie', 'age': 35}]
Ставь 👍 и забирай 📚 Базу знаний