🤔 Какие ограничения есть у рекурсии в Python?
Рекурсия — это мощный инструмент, но в Python она имеет ограничения, которые нужно учитывать при написании кода.
🟠Ограничение на глубину рекурсии (`sys.getrecursionlimit()`)
В Python по умолчанию рекурсия ограничена 1000 вызовами, чтобы избежать переполнения стека.
Если превысить этот лимит, программа вызовет ошибку
🚩Как изменить лимит?
Можно увеличить глубину рекурсии, но это небезопасно
🟠Рекурсия требует много памяти
Каждый рекурсивный вызов создаёт новый фрейм в стеке вызовов.
🟠Отсутствие оптимизации хвостовой рекурсии
Другие языки (например, Lisp, JavaScript) автоматически оптимизируют хвостовую рекурсию (Tail Call Optimization, TCO).
Python не делает этого, поэтому даже "идеальная" рекурсия всё равно переполняет стек.
🟠Рекурсия медленнее цикла
Рекурсивный вызов требует больше накладных расходов (создание стек-фреймов), чем обычный
Ставь 👍 и забирай 📚 Базу знаний
Рекурсия — это мощный инструмент, но в Python она имеет ограничения, которые нужно учитывать при написании кода.
🟠Ограничение на глубину рекурсии (`sys.getrecursionlimit()`)
В Python по умолчанию рекурсия ограничена 1000 вызовами, чтобы избежать переполнения стека.
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)
Ставь 👍 и забирай 📚 Базу знаний
👍5
🤔 Что быстрее — списки или кортежи?
Кортежи быстрее списков, так как они неизменяемы, легче и оптимальнее с точки зрения памяти. Это делает операции над ними (особенно доступ) немного производительнее.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Кортежи быстрее списков, так как они неизменяемы, легче и оптимальнее с точки зрения памяти. Это делает операции над ними (особенно доступ) немного производительнее.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍7🔥1💊1
🤔 Что такое деструктор класса?
Это специальный метод, который вызывается автоматически, когда объект класса уничтожается. В Python этот метод называется
🚩Определение и использование деструктора
Определяется внутри класса с помощью метода
🟠Класс
🟠Метод
🟠Деструктор
🚩Создание и уничтожение объекта
Когда объект класса создается, вызывается конструктор. Когда объект больше не нужен, вызывается деструктор:
🚩Важные замечания
🟠Сборка мусора
Python использует механизм сборки мусора для автоматического управления памятью. Когда объект больше не используется (например, нет активных ссылок на него), сборщик мусора удаляет объект и вызывает его деструктор.
🟠Неопределенное время вызова
Точное время вызова деструктора зависит от работы сборщика мусора. Это означает, что нельзя гарантировать момент вызова деструктора. Поэтому для критических операций лучше использовать явное управление ресурсами, например, с помощью контекстных менеджеров (
🟠Контекстные менеджеры
Для явного управления ресурсами и их освобождения в предсказуемый момент лучше использовать контекстные менеджеры.
Ставь 👍 и забирай 📚 Базу знаний
Это специальный метод, который вызывается автоматически, когда объект класса уничтожается. В Python этот метод называется
__del__(). Деструктор используется для выполнения операций очистки, таких как освобождение ресурсов или выполнение завершающих действий перед тем, как объект будет удален из памяти.🚩Определение и использование деструктора
Определяется внутри класса с помощью метода
__del__(). class FileManager:
def __init__(self, filename):
self.file = open(filename, 'w')
print(f"Файл {filename} открыт для записи.")
def write_data(self, data):
self.file.write(data)
def __del__(self):
self.file.close()
print("Файл закрыт.")
🟠Класс
FileManager имеет конструктор __init__(), который открывает файл для записи.🟠Метод
write_data() записывает данные в файл.🟠Деструктор
__del__() закрывает файл, когда объект FileManager уничтожается.🚩Создание и уничтожение объекта
Когда объект класса создается, вызывается конструктор. Когда объект больше не нужен, вызывается деструктор:
manager = FileManager('example.txt')
manager.write_data('Hello, world!')
# Когда объект manager больше не нужен, вызывается деструктор и файл закрывается🚩Важные замечания
🟠Сборка мусора
Python использует механизм сборки мусора для автоматического управления памятью. Когда объект больше не используется (например, нет активных ссылок на него), сборщик мусора удаляет объект и вызывает его деструктор.
🟠Неопределенное время вызова
Точное время вызова деструктора зависит от работы сборщика мусора. Это означает, что нельзя гарантировать момент вызова деструктора. Поэтому для критических операций лучше использовать явное управление ресурсами, например, с помощью контекстных менеджеров (
with).🟠Контекстные менеджеры
Для явного управления ресурсами и их освобождения в предсказуемый момент лучше использовать контекстные менеджеры.
with open('example.txt', 'w') as file:
file.write('Hello, world!')
# Файл автоматически закрывается после выхода из блока withСтавь 👍 и забирай 📚 Базу знаний
🔥3
🤔 Какие нововведения появились с версии Python 3.7?
Python 3.7 принёс несколько важных улучшений:
- Гарантия порядка в dict — словари сохраняют порядок вставки ключей (до этого поведение не было гарантировано).
- Модуль dataclasses — упрощённое объявление классов с полями.
- Новая система обнаружения и обработки прерываний (asyncio.run ()).
- getattr и dir на уровне модуля.
- Улучшения в производительности и стабильности, в том числе оптимизация вызовов функций.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Python 3.7 принёс несколько важных улучшений:
- Гарантия порядка в dict — словари сохраняют порядок вставки ключей (до этого поведение не было гарантировано).
- Модуль dataclasses — упрощённое объявление классов с полями.
- Новая система обнаружения и обработки прерываний (
- getattr и dir на уровне модуля.
- Улучшения в производительности и стабильности, в том числе оптимизация вызовов функций.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
💊9👍1
🤔 Почему оптимизация запросов — важный навык?
Потому что медленные SQL-запросы тормозят приложение, особенно при большом объёме данных. Оптимизация позволяет:
- повысить производительность БД;
- снизить нагрузку на сервер;
- ускорить отклик API;
- избежать проблем в продакшене;
- сократить время выполнения сложных операций.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Потому что медленные SQL-запросы тормозят приложение, особенно при большом объёме данных. Оптимизация позволяет:
- повысить производительность БД;
- снизить нагрузку на сервер;
- ускорить отклик API;
- избежать проблем в продакшене;
- сократить время выполнения сложных операций.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍3
🤔 Что в python не является объектом?
В Python практически всё является объектом: числа, строки, функции, классы, модули и даже сам интерпретатор Python рассматривает их как объекты. Однако есть несколько вещей, которые объектами не являются:
🟠Операторы и синтаксические конструкции
Операторы (
🟠Ключевые слова (keywords)
Встроенные ключевые слова Python (
🟠Идентификаторы переменных
Хотя переменные ссылаются на объекты, сами идентификаторы (имена переменных) — это просто ссылки, а не объекты.
🟠Аннотации типов во время компиляции
Аннотации типов в Python, такие как
Ставь 👍 и забирай 📚 Базу знаний
В Python практически всё является объектом: числа, строки, функции, классы, модули и даже сам интерпретатор Python рассматривает их как объекты. Однако есть несколько вещей, которые объектами не являются:
🟠Операторы и синтаксические конструкции
Операторы (
+, -, *, and, or, not и т. д.) сами по себе не являются объектами. Они — часть синтаксиса языка и не имеют представления в виде объектов в памяти.a = 10 + 5 # Оператор "+" выполняет сложение, но сам по себе не объект
print(type(+)) # Ошибка: нельзя получить тип оператора
🟠Ключевые слова (keywords)
Встроенные ключевые слова Python (
if, else, while, for, def, class, return и т. д.) не являются объектами. Они зарезервированы интерпретатором и используются для управления потоком выполнения кода.print(type(if)) # Ошибка: ключевое слово не является объектом
🟠Идентификаторы переменных
Хотя переменные ссылаются на объекты, сами идентификаторы (имена переменных) — это просто ссылки, а не объекты.
x = 42 # x — это имя, а не объект
print(type(x)) # Это целое число, но само имя "x" объектом не является
🟠Аннотации типов во время компиляции
Аннотации типов в Python, такие как
list[str], не создают объекты во время компиляции кода. Они интерпретируются только на уровне анализа типов.def func(x: int) -> str:
return str(x)
Ставь 👍 и забирай 📚 Базу знаний
👍8
🤔 Может ли метод объекта вернуть класс?
Да, метод объекта может вернуть класс. Например:
- Метод объекта может использовать имя класса через self.class.
- Это позволяет получить сам класс, к которому принадлежит объект.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Да, метод объекта может вернуть класс. Например:
- Метод объекта может использовать имя класса через self.class.
- Это позволяет получить сам класс, к которому принадлежит объект.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍3
🤔 Какие задачи хорошо параллелятся, какие плохо?
Параллельные вычисления — это выполнение нескольких задач одновременно, чтобы ускорить работу программы. Но не все задачи можно эффективно распараллелить.
🚩Независимые задачи (Embarrassingly Parallel Tasks)
Это задачи, которые можно выполнять полностью независимо друг от друга, без обмена данными.
Обработка изображений (фильтры, преобразования)
Генерация фрагментов видео
Рендеринг 3D-графики (каждый кадр рендерится отдельно)
Обучение моделей машинного обучения на разных данных (если без обмена параметрами)
🚩Численные вычисления на больших данных (SIMD-операции, GPU-ускорение)
Если однотипные операции выполняются на большом массиве данных, их можно делать параллельно.
Умножение матриц (используется в нейросетях)
Обработка сигналов (FFT, фильтрация)
Физические симуляции
🚩Веб-запросы и сетевые операции
Когда программа ждет ответа от сервера, процесс простаивает. Можно запускать запросы асинхронно, чтобы делать их параллельно.
Скачивание файлов
Парсинг веб-страниц
Вызовы API
Ставь 👍 и забирай 📚 Базу знаний
Параллельные вычисления — это выполнение нескольких задач одновременно, чтобы ускорить работу программы. Но не все задачи можно эффективно распараллелить.
🚩Независимые задачи (Embarrassingly Parallel Tasks)
Это задачи, которые можно выполнять полностью независимо друг от друга, без обмена данными.
Обработка изображений (фильтры, преобразования)
Генерация фрагментов видео
Рендеринг 3D-графики (каждый кадр рендерится отдельно)
Обучение моделей машинного обучения на разных данных (если без обмена параметрами)
from concurrent.futures import ProcessPoolExecutor
from PIL import Image
def process_image(image_path):
img = Image.open(image_path)
img = img.convert("L") # Перевод в черно-белый формат
img.save(f"processed_{image_path}")
images = ["img1.jpg", "img2.jpg", "img3.jpg"]
with ProcessPoolExecutor() as executor:
executor.map(process_image, images)
🚩Численные вычисления на больших данных (SIMD-операции, GPU-ускорение)
Если однотипные операции выполняются на большом массиве данных, их можно делать параллельно.
Умножение матриц (используется в нейросетях)
Обработка сигналов (FFT, фильтрация)
Физические симуляции
import numpy as np
A = np.random.rand(1000, 1000)
B = np.random.rand(1000, 1000)
C = A @ B # Быстрое умножение матриц (использует несколько ядер процессора)
🚩Веб-запросы и сетевые операции
Когда программа ждет ответа от сервера, процесс простаивает. Можно запускать запросы асинхронно, чтобы делать их параллельно.
Скачивание файлов
Парсинг веб-страниц
Вызовы API
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", "https://google.com"]
tasks = [fetch(url) for url in urls]
responses = await asyncio.gather(*tasks)
print(responses)
asyncio.run(main())
Ставь 👍 и забирай 📚 Базу знаний
👍2
🤔 Для чего применяются множества?
Они удобны для устранения дубликатов, выполнения математических операций над группами данных и ускоренной проверки вхождения. Также множества позволяют выполнять пересечения и объединения.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Они удобны для устранения дубликатов, выполнения математических операций над группами данных и ускоренной проверки вхождения. Также множества позволяют выполнять пересечения и объединения.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍6
🤔 Что такое циклы?
Циклы — это конструкции, которые позволяют многократно выполнять код, пока выполняется определённое условие.
В Python есть два типа циклов:
🚩Цикл `for` (перебор последовательностей)
Простой пример
Вывод
Перебор списка
Вывод
Перебор словаря (
Вывод
🚩Цикл `while` (работает, пока `True`)
Пример
Вывод
*
🚩3. Управление циклами (`break`, `continue`)
Вывод
Вывод
🚩`else` в циклах (`for` / `while`)
Вывод
Но если сработает
Вывод
Ставь 👍 и забирай 📚 Базу знаний
Циклы — это конструкции, которые позволяют многократно выполнять код, пока выполняется определённое условие.
В Python есть два типа циклов:
for — перебирает элементы последовательности (list, tuple, dict, range() и т. д.). while — выполняется, пока условие True. 🚩Цикл `for` (перебор последовательностей)
Простой пример
for for i in range(5):
print(i)
Вывод
0
1
2
3
4
Перебор списка
names = ["Alice", "Bob", "Charlie"]
for name in names:
print(name)
Вывод
Alice
Bob
Charlie
Перебор словаря (
dict) user = {"name": "Alice", "age": 25}
for key, value in user.items():
print(f"{key}: {value}")Вывод
name: Alice
age: 25
🚩Цикл `while` (работает, пока `True`)
Пример
while x = 0
while x < 5:
print(x)
x += 1
Вывод
0
1
2
3
4
*
while с input() (бесконечный цикл) while True:
command = input("Введите команду: ")
if command == "exit":
break # Выход из цикла
print(f"Вы ввели: {command}")
🚩3. Управление циклами (`break`, `continue`)
break — выход из цикла for i in range(10):
if i == 5:
break # Прерывает цикл, если i == 5
print(i)
Вывод
0
1
2
3
4
continue — пропуск итерации for i in range(5):
if i == 2:
continue # Пропускаем 2
print(i)
Вывод
0
1
3
4
🚩`else` в циклах (`for` / `while`)
else выполняется, если цикл завершился без break for i in range(5):
print(i)
else:
print("Цикл завершён!")
Вывод
0
1
2
3
4
Цикл завершён!
Но если сработает
break, else не выполняется for i in range(5):
if i == 3:
break
print(i)
else:
print("Цикл завершён!") # Не выполнится!
Вывод
0
1
2
Ставь 👍 и забирай 📚 Базу знаний
👍7💊2
🤔 Что такое HTTP?
HTTP (HyperText Transfer Protocol) — это протокол прикладного уровня, по которому клиент (чаще всего браузер) и сервер обмениваются сообщениями.
Клиент отправляет запрос (method + URL + headers + body), а сервер возвращает ответ (status code + headers + body).
HTTP работает по модели запрос-ответ, не хранит состояние между запросами (stateless), и его современая версия — HTTP/2 или HTTP/3.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
HTTP (HyperText Transfer Protocol) — это протокол прикладного уровня, по которому клиент (чаще всего браузер) и сервер обмениваются сообщениями.
Клиент отправляет запрос (method + URL + headers + body), а сервер возвращает ответ (status code + headers + body).
HTTP работает по модели запрос-ответ, не хранит состояние между запросами (stateless), и его современая версия — HTTP/2 или HTTP/3.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍10🤔1
🤔 Что такое type?
В Python
Определяет тип объекта (
Создаёт новые классы динамически (
🟠1. `type(obj)`: Определение типа объекта
Функция
🟠`type(name, bases, attrs)`: Создание класса динамически
Функция
🟠`type` как метакласс
В Python
Ставь 👍 и забирай 📚 Базу знаний
В Python
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'>
Ставь 👍 и забирай 📚 Базу знаний
👍2
🤔 Что такое await?
await — ключевое слово в Python, которое приостанавливает выполнение функции, пока не завершится корутина или awaitable-объект. Оно передаёт управление event loop'у, позволяя другим задачам выполняться в это время.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
await — ключевое слово в Python, которое приостанавливает выполнение функции, пока не завершится корутина или awaitable-объект. Оно передаёт управление event loop'у, позволяя другим задачам выполняться в это время.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍7
🤔 Что такое хранитель (Memento)?
Это поведенческий паттерн проектирования, который позволяет сохранять и восстанавливать предыдущее состояние объекта без нарушения инкапсуляции. Этот паттерн особенно полезен для реализации операций отмены и повтора, так как он позволяет хранить состояния объектов и возвращать их к этим состояниям по необходимости.
🚩Зачем нужен?
🟠Сохранение состояния:
Позволяет сохранять текущее состояние объекта и восстанавливать его позже.
🟠Инкапсуляция:
Обеспечивает сохранение состояния объекта без нарушения его инкапсуляции. Внутренние детали объекта остаются скрытыми от других объектов.
🟠Отмена и повтор операций:
Поддерживает функциональность отмены и повтора операций, так как позволяет возвращать объект к предыдущим состояниям.
Пример реализации
1⃣`Memento`:
Сохраняет состояние объекта. Он предоставляет методы для получения сохраненного состояния, но не предоставляет методов для изменения состояния, что обеспечивает неизменность.
2⃣`TextEditor`:
Создает и использует объекты
3⃣`_save_state`:
Сохраняет текущее состояние редактора в истории перед каждым изменением.
4⃣`undo`:
Восстанавливает предыдущее состояние редактора из истории.
Ставь 👍 и забирай 📚 Базу знаний
Это поведенческий паттерн проектирования, который позволяет сохранять и восстанавливать предыдущее состояние объекта без нарушения инкапсуляции. Этот паттерн особенно полезен для реализации операций отмены и повтора, так как он позволяет хранить состояния объектов и возвращать их к этим состояниям по необходимости.
🚩Зачем нужен?
🟠Сохранение состояния:
Позволяет сохранять текущее состояние объекта и восстанавливать его позже.
🟠Инкапсуляция:
Обеспечивает сохранение состояния объекта без нарушения его инкапсуляции. Внутренние детали объекта остаются скрытыми от других объектов.
🟠Отмена и повтор операций:
Поддерживает функциональность отмены и повтора операций, так как позволяет возвращать объект к предыдущим состояниям.
Пример реализации
class Memento:
def __init__(self, state: str):
self._state = state
def get_state(self) -> str:
return self._state
class TextEditor:
def __init__(self):
self._state = ""
self._history = []
def type(self, text: str):
self._save_state()
self._state += text
def _save_state(self):
self._history.append(Memento(self._state))
def undo(self):
if not self._history:
return
memento = self._history.pop()
self._state = memento.get_state()
def get_content(self) -> str:
return self._state
# Клиентский код для использования паттерна Хранитель
def main():
editor = TextEditor()
editor.type("Hello, ")
editor.type("world!")
print(editor.get_content()) # Hello, world!
editor.undo()
print(editor.get_content()) # Hello,
editor.undo()
print(editor.get_content()) #
if __name__ == "__main__":
main()
1⃣`Memento`:
Сохраняет состояние объекта. Он предоставляет методы для получения сохраненного состояния, но не предоставляет методов для изменения состояния, что обеспечивает неизменность.
2⃣`TextEditor`:
Создает и использует объекты
Memento для сохранения и восстановления своего состояния. Методы type и undo позволяют редактировать текст и отменять изменения.3⃣`_save_state`:
Сохраняет текущее состояние редактора в истории перед каждым изменением.
4⃣`undo`:
Восстанавливает предыдущее состояние редактора из истории.
Ставь 👍 и забирай 📚 Базу знаний
👍1
🤔 Что такое force push?
Это принудительная отправка изменений в удалённую ветку, даже если история расходится. Используется с осторожностью, так как может привести к потере коммитов.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Это принудительная отправка изменений в удалённую ветку, даже если история расходится. Используется с осторожностью, так как может привести к потере коммитов.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍4
🤔 Что такое клиент-серверная архитектура?
Клиент-серверная архитектура – это модель взаимодействия устройств, где клиент запрашивает данные или услуги, а сервер их предоставляет.
🚩Как это работает?
Клиент – это программа или устройство, которое отправляет запросы (например, браузер).
Сервер – это программа или устройство, которое обрабатывает запросы и отправляет ответ (например, веб-сервер).
Сервер (сервер.py)
Клиент (клиент.py)
🚩Как это работает?
1⃣Запускаем
2⃣Запускаем
3⃣Сервер получает сообщение, отвечает клиенту и закрывает соединение.
4⃣Клиент принимает ответ и завершает работу.
🚩Типы клиент-серверных архитектур
Одноуровневая – клиент общается напрямую с сервером.
Двухуровневая – классическая схема "клиент сервер" (например, браузер веб-сервер).
Трёхуровневая – добавляется база данных (например, клиент сервер БД).
Многоуровневая – сложные распределённые системы с несколькими серверами (например, микросервисы).
Ставь 👍 и забирай 📚 Базу знаний
Клиент-серверная архитектура – это модель взаимодействия устройств, где клиент запрашивает данные или услуги, а сервер их предоставляет.
🚩Как это работает?
Клиент – это программа или устройство, которое отправляет запросы (например, браузер).
Сервер – это программа или устройство, которое обрабатывает запросы и отправляет ответ (например, веб-сервер).
Сервер (сервер.py)
import socket
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("localhost", 8080)) # Привязываем сервер к адресу и порту
server.listen(1) # Ожидаем подключения одного клиента
print("Сервер запущен и ждёт подключения...")
conn, addr = server.accept() # Принимаем подключение
print(f"Подключен клиент: {addr}")
data = conn.recv(1024).decode() # Читаем данные от клиента
print(f"Клиент прислал: {data}")
conn.send("Привет от сервера!".encode()) # Отправляем ответ клиенту
conn.close()
Клиент (клиент.py)
import socket
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(("localhost", 8080)) # Подключаемся к серверу
client.send("Привет, сервер!".encode()) # Отправляем сообщение
response = client.recv(1024).decode() # Получаем ответ от сервера
print(f"Ответ сервера: {response}")
client.close()
🚩Как это работает?
1⃣Запускаем
сервер.py. Он ждёт подключения. 2⃣Запускаем
клиент.py. Клиент подключается к серверу и отправляет сообщение. 3⃣Сервер получает сообщение, отвечает клиенту и закрывает соединение.
4⃣Клиент принимает ответ и завершает работу.
🚩Типы клиент-серверных архитектур
Одноуровневая – клиент общается напрямую с сервером.
Двухуровневая – классическая схема "клиент сервер" (например, браузер веб-сервер).
Трёхуровневая – добавляется база данных (например, клиент сервер БД).
Многоуровневая – сложные распределённые системы с несколькими серверами (например, микросервисы).
Ставь 👍 и забирай 📚 Базу знаний
👍4🔥1
🤔 Как посмотреть примерное количество записей в БД?
- В SQL: SELECT COUNT(*) FROM table;
- В MongoDB: db.collection.estimatedDocumentCount() — быстрое, но неточное;
- Или countDocuments() — точное, но медленнее.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
- В SQL: SELECT COUNT(*) FROM table;
- В MongoDB: db.collection.estimatedDocumentCount() — быстрое, но неточное;
- Или countDocuments() — точное, но медленнее.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍2
🤔 Почему поиск по ключам в словаре работает быстро?
В Python словари (
🟠Как устроен словарь в Python?
Словарь (
🟠Как работает хеш-таблица?
Основной принцип:
Хеш-функция (
Используется массив (таблица), где данные хранятся по индексам, связанным с хешем.
Поиск по ключу — это просто вычисление хеша и обращение к нужному индексу.
Когда мы пишем
🟠Почему поиск занимает O(1)?
Нет линейного поиска: вместо перебора всех элементов Python сразу вычисляет, где находится нужное значение.
Операция доступа занимает фиксированное время:
Даже при большом количестве элементов скорость остается высокой.
Добавим 1 миллион элементов и посмотрим скорость поиска:
🟠Что если хеши совпадут? (Коллизии)
Иногда два разных ключа могут иметь одинаковый хеш (редко, но возможно). Тогда Python использует связанный список (chaining) или перехеширование.
Ставь 👍 и забирай 📚 Базу знаний
В Python словари (
dict) работают очень быстро, потому что они используют хеш-таблицы. Это позволяет находить значения по ключу в константное время O(1) в большинстве случаев. Давайте разберемся, как это работает.🟠Как устроен словарь в Python?
Словарь (
dict) — это структура данных, которая хранит пары ключ → значение. Например:data = {"name": "Alice", "age": 25, "city": "New York"}
print(data["age"]) # 25🟠Как работает хеш-таблица?
Основной принцип:
Хеш-функция (
hash()) вычисляет уникальное число (хеш) для ключа.Используется массив (таблица), где данные хранятся по индексам, связанным с хешем.
Поиск по ключу — это просто вычисление хеша и обращение к нужному индексу.
print(hash("age")) # Например, вернет 328847234 (будет разным при каждом запуске)Когда мы пишем
value = data["age"]
🟠Почему поиск занимает O(1)?
Нет линейного поиска: вместо перебора всех элементов Python сразу вычисляет, где находится нужное значение.
Операция доступа занимает фиксированное время:
hash() + обращение по индексу.Даже при большом количестве элементов скорость остается высокой.
Добавим 1 миллион элементов и посмотрим скорость поиска:
import time
data = {i: i * 2 for i in range(1_000_000)}
start = time.time()
print(data[999_999]) # Быстро находит ключ!
end = time.time()
print("Время поиска:", end - start) # Около 0.000001 сек
🟠Что если хеши совпадут? (Коллизии)
Иногда два разных ключа могут иметь одинаковый хеш (редко, но возможно). Тогда Python использует связанный список (chaining) или перехеширование.
print(hash("abc") % 10) # Например, 5
print(hash("xyz") % 10) # Тоже 5 (редко, но бывает)Ставь 👍 и забирай 📚 Базу знаний
👍4💊3
🤔 Что знаешь про два основных типа данных Python?
Основные типы данных Python — изменяемые (списки, множества, словари) и неизменяемые (строки, числа, кортежи). Изменяемые можно модифицировать после создания, тогда как неизменяемые остаются неизменными.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍7💊5
🤔 Зачем нужны классы BaseExceptionGroup и ExceptionGroup?
В Python 3.11 были добавлены новые классы исключений
🚩Зачем нужны `BaseExceptionGroup` и `ExceptionGroup`?
Ранее в Python было возможно выбросить только одно исключение за раз, и обработка нескольких исключений одновременно требовала сложного и неочевидного кода. Например:
При работе с асинхронными функциями или потоками может возникнуть сразу несколько ошибок, и их нужно корректно обработать.
В больших приложениях или библиотеках (например, при работе с
🚩Разница между `BaseExceptionGroup` и `ExceptionGroup`
🚩Как они работают?
Классы исключений
Указать несколько ошибок одновременно.
Позволить обработчику исключений работать с каждым из них.
Результат
🚩Обработка групп исключений
При обработке
Результат
🚩Преимущества использования
➕Работа с несколькими исключениями одновременно.
Вы можете объединить связанные ошибки и передать их в одном объекте.
➕Четкое разграничение типов исключений.
Использование
➕Удобство при асинхронном программировании.
В асинхронных задачах (
➕Упрощение сложной логики.
Код становится проще и понятнее, так как не нужно вручную собирать и разбирать исключения.
🚩Когда использовать?
Когда вы работаете с несколькими задачами, которые могут порождать ошибки одновременно (например, асинхронный код).
Когда вы хотите сообщить о нескольких связанных ошибках, не выбрасывая каждую из них отдельно.
Когда требуется раздельная обработка разных типов ошибок.
Ставь 👍 и забирай 📚 Базу знаний
В Python 3.11 были добавлены новые классы исключений
BaseExceptionGroup и ExceptionGroup. Эти классы решают проблему одновременной обработки нескольких исключений, которые могут возникать в сложных ситуациях, таких как асинхронное программирование, многопоточность или обработка нескольких связанных ошибок. Давайте разберем, зачем они нужны, как их использовать и какие преимущества они дают.🚩Зачем нужны `BaseExceptionGroup` и `ExceptionGroup`?
Ранее в Python было возможно выбросить только одно исключение за раз, и обработка нескольких исключений одновременно требовала сложного и неочевидного кода. Например:
При работе с асинхронными функциями или потоками может возникнуть сразу несколько ошибок, и их нужно корректно обработать.
В больших приложениях или библиотеках (например, при работе с
asyncio) может быть необходимость передать сразу несколько исключений, которые произошли в разных местах, как единый объект.BaseExceptionGroup и его подкласс ExceptionGroup позволяют группировать несколько исключений и выбрасывать их вместе в виде одного объекта. Это делает код более читаемым, упрощает обработку и исключает необходимость ручной агрегации ошибок.🚩Разница между `BaseExceptionGroup` и `ExceptionGroup`
BaseExceptionGroup - это базовый класс для группировки исключений. Он наследуется от BaseException и, как правило, не используется напрямую.ExceptionGroup - это подкласс, который наследуется от Exception. Этот класс используется для обработки групп исключений, которые возникают при обычных ошибках в коде (не фатальных).🚩Как они работают?
Классы исключений
BaseExceptionGroup и ExceptionGroup позволяют создать "группу исключений", которая содержит несколько отдельных исключений. Это полезно, когда вам нужно:Указать несколько ошибок одновременно.
Позволить обработчику исключений работать с каждым из них.
def task_1():
raise ValueError("Ошибка в задаче 1")
def task_2():
raise TypeError("Ошибка в задаче 2")
try:
# Создаем группу исключений
raise ExceptionGroup(
"Ошибки в задачах",
[ValueError("Ошибка в задаче 1"), TypeError("Ошибка в задаче 2")]
)
except ExceptionGroup as eg:
for exc in eg.exceptions:
print(f"Обнаружено исключение: {exc}")
Результат
Обнаружено исключение: Ошибка в задаче 1
Обнаружено исключение: Ошибка в задаче 2
🚩Обработка групп исключений
При обработке
ExceptionGroup можно использовать механизм фильтрации с помощью конструкции except*. Это нововведение в Python 3.11 позволяет обрабатывать разные типы исключений внутри группы по-разному.try:
raise ExceptionGroup(
"Ошибки в задачах",
[ValueError("Ошибка 1"), TypeError("Ошибка 2"), ValueError("Ошибка 3")]
)
except* ValueError as ve:
print("Обрабатываем ValueError:", ve)
except* TypeError as te:
print("Обрабатываем TypeError:", te)
Результат
Обрабатываем ValueError: Ошибка 1
Обрабатываем ValueError: Ошибка 3
Обрабатываем TypeError: Ошибка 2
🚩Преимущества использования
➕Работа с несколькими исключениями одновременно.
Вы можете объединить связанные ошибки и передать их в одном объекте.
➕Четкое разграничение типов исключений.
Использование
except* позволяет обработать каждое исключение из группы отдельно, не теряя гибкости.➕Удобство при асинхронном программировании.
В асинхронных задачах (
asyncio) часто возникает несколько ошибок одновременно, и их можно группировать для дальнейшей обработки.➕Упрощение сложной логики.
Код становится проще и понятнее, так как не нужно вручную собирать и разбирать исключения.
🚩Когда использовать?
Когда вы работаете с несколькими задачами, которые могут порождать ошибки одновременно (например, асинхронный код).
Когда вы хотите сообщить о нескольких связанных ошибках, не выбрасывая каждую из них отдельно.
Когда требуется раздельная обработка разных типов ошибок.
Ставь 👍 и забирай 📚 Базу знаний
👍1