Python | Вопросы собесов
13.9K subscribers
35 photos
1 video
1 file
918 links
Cайт: easyoffer.ru
Реклама: @easyoffer_adv
ВП: @easyoffer_vp

Тесты t.me/+20tRfhrwPpM4NDQy
Задачи t.me/+nsl4meWmhfQwNDVi
Вакансии t.me/+cXGKkrOY2-w3ZTky
Download Telegram
🤔 Что известно о парадигмах?

1. Императивная парадигма: использование команд для изменения состояния программы.
2. Объектно-ориентированная: работа с классами и объектами.
3. Функциональная: поддержка высших функций, замыканий и итераторов.
4. Процедурная: выполнение программ как последовательности процедур.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
🤔 Что такое хешируемые типы данных?

Это такие типы данных, которые имеют постоянное (неизменяемое) хеш-значение на протяжении всего времени их существования. Это означает, что их можно использовать в качестве ключей в словарях (dict) и элементов в множествах (set), так как они поддерживают вычисление хеша с помощью функции hash().

🚩Как понять, что объект хешируемый?

🟠Объект должен быть неизменяемым
если объект можно изменить после создания, его хеш тоже изменится, что нарушает работу структур данных (словари, множества).
🟠Должен реализовывать метод `__hash__()`
который возвращает уникальный идентификатор объекта.

🚩Какие типы данных хешируемые?

Числа (int, float, complex)
  print(hash(42))       # 42
print(hash(3.14)) # 322818021289917443
print(hash(1 + 2j)) # 8389048192121911274


Строки (str)
print(hash("hello"))  # Например, 5320385861927423548


Кортежи (tuple), если все их элементы тоже хешируемые:
print(hash((1, 2, 3)))  # 529344067295497451


Булевы значения (bool):
  print(hash(True))   # 1
print(hash(False)) # 0


🚩Какие типы НЕ хешируемые?

Списки (list)
hash([1, 2, 3])  # TypeError: unhashable type: 'list'


Множества (set)
hash({1, 2, 3})  # TypeError: unhashable type: 'set'


Словари (dict)
hash({"a": 1})  # TypeError: unhashable type: 'dict'


🚩Почему это важно?

Хешируемые типы используются в словари (dict) и множества (set), так как они используют хеш-функцию для быстрого поиска данных.
my_dict = { (1, 2, 3): "tuple_key" }  # Работает, потому что кортеж неизменяемый
my_set = { 42, "hello", (1, 2) } # Все элементы хешируемые


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
🤔 Как происходит поиск переменной по области видимости?

Python ищет переменные по правилу LEGB:
- Local — локальная область внутри функции.
- Enclosing — области вложенных функций (для замыканий).
- Global — глобальная область модуля.
- Built-in — встроенные объекты Python.
Поиск идёт сверху вниз, и как только переменная найдена — поиск останавливается.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
🤔 Как можно оптимизировать хвостовую рекурсию в Python?

Хвостовая рекурсия (tail recursion) — это особый вид рекурсии, когда рекурсивный вызов является последней операцией в функции. В языках, поддерживающих оптимизацию хвостовой рекурсии (TCO – Tail Call Optimization), такие вызовы не создают новый стек вызовов, а переиспользуют текущий, что предотвращает переполнение стека.
Но в Python хвостовая рекурсия НЕ оптимизируется из-за особенностей интерпретатора (Python хранит полную историю вызовов для отладки).

🚩Способы оптимизации хвостовой рекурсии в Python

🟠Использование явного стека вместо рекурсии (итерация)
Лучший способ избежать проблем с глубокой рекурсией — заменить её циклом.
def factorial(n, acc=1):
if n == 0:
return acc
return factorial(n - 1, acc * n) # Хвостовая рекурсия (но Python не оптимизирует!)


Решение: заменить на цикл (итеративный подход)
def factorial_iter(n):
acc = 1
while n > 0:
acc *= n
n -= 1
return acc

print(factorial_iter(10000)) # Работает без ошибок


🟠Использование `sys.setrecursionlimit()` (не рекомендуется)
Python имеет ограничение на глубину рекурсии (обычно около 1000). Можно его увеличить
import sys
sys.setrecursionlimit(20000) # Увеличение лимита


🟠Использование `functools.lru_cache()` (мемоизация)
Если рекурсивная функция пересчитывает одни и те же значения, можно кешировать результаты.
from functools import lru_cache

@lru_cache(None) # Кеширует все вызовы функции
def fibonacci(n):
if n < 2:
return n
return fibonacci(n - 1) + fibonacci(n - 2)

print(fibonacci(100)) # Работает быстро, без переполнения стека


🟠Использование `stack` вместо рекурсии (эмуляция стека)
Если алгоритм требует рекурсии, но стек ограничен, можно использовать список как стек.
def factorial_stack(n):
stack = [(n, 1)]
while stack:
n, acc = stack.pop()
if n == 0:
return acc
stack.append((n - 1, acc * n))

print(factorial_stack(10000)) # Работает без ошибок


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
🤔 Какие преимущества генератора относительно функции?

Генераторы позволяют создавать значения "по требованию", без необходимости хранить их все в памяти. Они экономят ресурсы при работе с большими объёмами данных. Генераторы удобны для ленивых вычислений, бесконечных последовательностей и обработки потоков данных.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7💊2👍1
🤔 Как управлять кешированием в HTTP?

Кэширование в HTTP позволяет уменьшить нагрузку на сервер и ускорить загрузку страниц за счёт сохранения копий ресурсов.
Управление кэшем происходит через HTTP-заголовки, которые указывают, как долго хранить данные и когда обновлять их.

🟠Управление кэшированием через `Cache-Control`
Cache-Control — основной заголовок для кэширования, который указывает, как долго хранить ресурс и когда обновлять его.
Cache-Control: no-cache            # Браузер всегда запрашивает ресурс заново
Cache-Control: no-store # Запрещает кэширование вообще
Cache-Control: public, max-age=3600 # Кэшировать 1 час (3600 секунд)
Cache-Control: private, max-age=600 # Кэш только для одного пользователя (например, личный кабинет)
Cache-Control: must-revalidate # Клиент должен проверять, истёк ли срок кэша перед загрузкой


🟠Управление кэшем с `ETag` (оптимизированное обновление)
ETag — это уникальный идентификатор версии файла.
Сервер отправляет ресурс с ETag:
ETag: "abc123"

При следующем запросе браузер отправляет If-None-Match:
If-None-Match: "abc123"


Если ресурс не изменился, сервер отвечает 304 Not Modified (клиент использует кэш).
Если ресурс изменился — сервер отправляет новую версию.
HTTP/1.1 304 Not Modified


🟠Кэширование через `Last-Modified`
Работает аналогично ETag, но вместо идентификатора используется дата последнего изменения.
Сервер отправляет заголовок
Last-Modified: Wed, 21 Feb 2024 10:00:00 GMT


Браузер запрашивает ресурс с If-Modified-Since
If-Modified-Since: Wed, 21 Feb 2024 10:00:00 GMT


🟠Полное отключение кэша
Если нужно всегда загружать свежие данные, используем:
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache # Устарел, но нужен для старых браузеров
Expires: 0


🟠Управление кэшем через `Vary`
Если ресурс зависит от заголовков (User-Agent, Accept-Encoding), используем Vary.
Vary: User-Agent


🟠Принудительное обновление кэша (Cache Busting)
Если сервер отправил старый кэш, можно обновить ресурс с новым URL.
Способы
Добавить версию в URL
/style.css?v=2


Использовать хеш в имени файла:
/style.abc123.css


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🔥1
🤔 Можно ли использовать несколько декораторов для одной функции?

Да, декораторы можно накладывать друг на друга. Они применяются сверху вниз, но выполняются в обратном порядке.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
🤔 Что такое паттерн Мост (Bridge)?

Паттерн "Мост" (Bridge) является структурным паттерном проектирования, который предназначен для разделения абстракции и реализации так, чтобы они могли изменяться независимо друг от друга. Этот паттерн полезен, когда класс должен работать с различными платформами или когда нужно избежать жесткой связки между абстракцией и ее реализацией.

🚩 Зачем нужен

🟠Разделение абстракции и реализации:
Он позволяет отделить абстракцию от ее реализации, что упрощает поддержку и расширение системы.
🟠Уменьшение количества подклассов:
Без применения этого паттерна, если у нас есть несколько вариантов абстракции и несколько вариантов реализации, то нам пришлось бы создавать классы для всех возможных комбинаций, что приводит к взрывному росту количества классов.
🟠Гибкость:
Это позволяет изменять и абстракцию, и реализацию независимо друг от друга.

🚩Как используется

🟠Абстракция (Abstraction):
Определяет интерфейс и хранит ссылку на объект Implementor.
🟠Расширенная абстракция (RefinedAbstraction):
Наследует Abstraction и расширяет интерфейс.
🟠Реализатор (Implementor):
Определяет интерфейс для всех реализаций.
🟠Конкретный реализатор (ConcreteImplementor):
Реализует интерфейс Implementor.

Допустим, у нас есть программа для управления различными типами устройств (например, телевизор и радио), которые можно включать и выключать. Мы хотим, чтобы способ управления устройствами мог изменяться независимо от типов устройств.
# Implementor
class Device:
def is_enabled(self):
pass

def enable(self):
pass

def disable(self):
pass

# ConcreteImplementor
class TV(Device):
def __init__(self):
self._on = False

def is_enabled(self):
return self._on

def enable(self):
self._on = True

def disable(self):
self._on = False

class Radio(Device):
def __init__(self):
self._on = False

def is_enabled(self):
return self._on

def enable(self):
self._on = True

def disable(self):
self._on = False

# Abstraction
class RemoteControl:
def __init__(self, device):
self._device = device

def toggle_power(self):
if self._device.is_enabled():
self._device.disable()
else:
self._device.enable()

# RefinedAbstraction
class AdvancedRemoteControl(RemoteControl):
def mute(self):
print("Device is muted.")

# Клиентский код
tv = TV()
remote = RemoteControl(tv)
remote.toggle_power() # Включает TV

radio = Radio()
advanced_remote = AdvancedRemoteControl(radio)
advanced_remote.toggle_power() # Включает Radio
advanced_remote.mute() # Заглушает Radio


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🤔2
🤔 В чём разница типов данных?

Типы данных в Python делятся на:
- Неизменяемые (immutable): int, float, str, tuple, frozenset.
- Изменяемые (mutable): list, dict, set, bytearray.
Изменяемые объекты могут быть модифицированы без изменения их идентификатора (id()), в то время как неизменяемые создают новый объект при любом изменении. Это влияет на поведение в функциях, при копировании, в кэшировании и в хешировании.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
🤔 Зачем нужны схемы в БД?

Схема (schema) в базе данных — это логическая группировка объектов (таблиц, индексов, представлений и т. д.) внутри одной БД.

🚩Что такое схема в БД?

Схема — это контейнер для объектов БД (таблиц, индексов, процедур).
База данных (company_db)
├── Схема: public (по умолчанию)
│ ├── Таблица: employees
│ ├── Таблица: departments
├── Схема: hr
│ ├── Таблица: employees
│ ├── Таблица: salaries
├── Схема: sales
│ ├── Таблица: customers
│ ├── Таблица: orders


🚩Как создавать и использовать схемы?

Создание схемы (CREATE SCHEMA)
CREATE SCHEMA hr;  -- Создаём схему "hr"


Создание таблицы внутри схемы
CREATE TABLE hr.employees (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
position VARCHAR(50)
);


Выбор схемы по умолчанию
SET search_path TO hr;


🚩Где полезны схемы?

🟠Разделение данных по модулям
Если в БД хранятся разные области бизнеса (кадры, продажи, финансы), их можно разделить по схемам:
- hr.employees, hr.salaries
- sales.orders, sales.customers

🟠Разные версии одной БД
Например, в PostgreSQL можно создать схему dev для тестов:
- dev.users — тестовая версия таблицы
- prod.users — продакшен-версия

🟠Безопасность и доступ пользователей
Можно дать доступ к разным схемам разным пользователям:
GRANT USAGE ON SCHEMA hr TO hr_manager;
GRANT SELECT ON ALL TABLES IN SCHEMA hr TO hr_manager;


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥2
🤔 Что такое SSL и TLS?

SSL (Secure Sockets Layer) и TLS (Transport Layer Security) — это криптографические протоколы, которые обеспечивают защищённую передачу данных по сети.
SSL — это более старая версия, которая больше не используется из-за уязвимостей.
TLS — это современный и надёжный протокол, который обеспечивает шифрование, целостность и аутентификацию при передаче данных.
Именно благодаря TLS сайты работают по защищённому протоколу HTTPS.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🔥1🤔1💊1
🤔 Объясни как происходит обработка HTTP запросов на Django

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

🚩Подробный разбор обработки HTTP-запроса в Django

🟠Запрос приходит в WSGI/ASGI сервер
Когда клиент (браузер, API) отправляет запрос, его принимает WSGI/ASGI-сервер (Gunicorn, Daphne).
Если проект синхронный → работает через WSGI (wsgi.py).
Если проект асинхронный → через ASGI (asgi.py).
GET /hello/ HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0


🟠Django создаёт `HttpRequest` объект
Django превращает HTTP-запрос в объект HttpRequest, который передаётся в view.
def my_view(request):
print(request.method) # 'GET'
print(request.path) # '/hello/'
print(request.GET) # {'name': 'Alice'}


🟠Middleware (промежуточная обработка)
Прежде чем запрос дойдёт до view, Django проходит через мидлвари, которые могут:
Проверять авторизацию (AuthenticationMiddleware).
Защищать от CSRF (CsrfViewMiddleware).
Перенаправлять запросы (CommonMiddleware).
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
]


🟠Поиск `view` в `urls.py`
Django ищет, какая функция (view) должна обработать этот URL.
from django.urls import path
from myapp.views import hello_view

urlpatterns = [
path("hello/", hello_view), # Запрос "/hello/" попадёт в hello_view
]


🟠Выполнение `view` (контроллера)
Когда Django находит подходящее представление (view), оно вызывается.
from django.http import HttpResponse

def hello_view(request):
return HttpResponse("Привет, мир!")


🟠Формирование и обработка ответа
Django берёт HttpResponse и передаёт его обратно через middleware (например, сжатие, защита, заголовки безопасности).
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 12

Привет, мир!


🟠WSGI/ASGI сервер отправляет ответ клиенту
На последнем этапе WSGI/ASGI-сервер отправляет ответ обратно браузеру или API-клиенту.


🚩Краткая схема обработки запроса

Клиент (браузер) → WSGI/ASGI → Django Middleware → URL Dispatcher → View → Response → Клиент


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10
🤔 Что за функция wait()?

wait() похожа на gather, но предоставляет более гибкий контроль, позволяя:
- ждать завершения всех задач;
- ждать первых завершённых;
- получить информацию о выполненных и ожидающих задачах.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7💊1
🤔 В чем отличие изменяемые / неизменяемые?

В Python все данные делятся на изменяемые (mutable) и неизменяемые (immutable)

🚩Неизменяемые (`immutable`) типы

После создания их нельзя изменить!
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]] Не изменился!


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
🤔 Как создать views?

Views создаются как функции или классы в файле views.py, которые принимают запрос и возвращают HTTP-ответ. Например, с использованием функций HttpResponse или рендеринга шаблонов через render.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
🤔 Что такое RESTful?

Это подход к проектированию веб-сервисов, основанный на архитектурном стиле REST (*Representational State Transfer*). Это не протокол или стандарт, а набор принципов и ограничений, которые используются для создания систем, взаимодействующих через HTTP. Если API соответствует этим принципам, его называют RESTful.

🚩 Основные принципы REST

🟠Клиент-серверная архитектура
Клиент (например, браузер или мобильное приложение) и сервер (где размещена база данных и логика обработки данных) чётко разделены:
Клиент запрашивает данные или отправляет запросы к серверу.
Сервер отвечает, предоставляя ресурсы или выполняя действия.

🟠Состояние отсутствия (Stateless)
Каждый запрос от клиента к серверу должен быть самодостаточным. Это означает, что сервер не хранит информацию о состоянии клиента между запросами. Вся необходимая информация передается в запросе (например, токен аутентификации).

🟠Унифицированный интерфейс
RESTful API использует единый, стандартный интерфейс для взаимодействия. Это достигается следующими средствами:
Идентификация ресурсов через URI: Каждый ресурс имеет уникальный адрес (URI).

     GET https://api.example.com/users/123

Использование стандартных HTTP-методов:
GET — для получения данных.
POST — для создания новых данных.
PUT или PATCH — для обновления данных.
DELETE — для удаления данных.
Ресурсы как представления: Ресурсы передаются в формате JSON, XML или другом формате.

🟠Кэширование
Ответы сервера могут быть кэшируемыми. Это уменьшает нагрузку на сервер и ускоряет работу клиента.

🟠Единообразие и слои
RESTful системы могут включать несколько слоев (например, балансировщики нагрузки, кеш-сервисы), но клиент взаимодействует только с сервером, не зная о внутренних слоях.

🟠Код по требованию (опционально)
Иногда сервер может передавать исполняемый код (например, JavaScript) клиенту, чтобы расширить его функциональность. Это не обязательно.

🚩Почему RESTful важен?

RESTful архитектура позволяет:
🟠Сделать API простым и понятным
Клиенты легко понимают, как обращаться к ресурсам (используя стандартные методы и адреса).
🟠Обеспечить гибкость
Клиенты и серверы могут развиваться независимо друг от друга.
🟠Поддерживать масштабируемость
RESTful API легко масштабируются, так как все запросы независимы друг от друга (статичность).
🟠Облегчить интеграцию
RESTful API поддерживают стандартизированные протоколы (HTTP), что делает интеграцию с другими сервисами проще.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
🤔 Какие декораторы использовал?

На практике применяются такие декораторы:
-
@staticmethod — обозначает метод, не использующий self.
-
@classmethod — получает cls и работает с классом, а не экземпляром.
-
@property — превращает метод в геттер (доступ к методу как к атрибуту).
-
@lru_cache — кеширует вызовы функции, оптимизируя повторные вычисления.
-
@wraps — сохраняет метаинформацию оригинальной функции в пользовательских декораторах.
- Декораторы логирования, валидации, измерения времени выполнения.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3
🤔 Как работает пакетирование библиотек Python?

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

🚩Что такое пакет Python?

Пакет — это набор модулей, объединенных в одну структуру (обычно это папка с файлом __init__.py).
mypackage/
│── mymodule.py
│── __init__.py
└── utils.py


🚩Как создать свой пакет?

Допустим, у нас есть пакет mypackage, в котором есть функция say_hello().

Структура проекта
mypackage/
│── mymodule.py
│── __init__.py
└── setup.py


Файл mypackage/mymodule.py
def say_hello():
return "Привет, мир!"


Файл mypackage/__init__.py (он делает папку пакетом)
from .mymodule import say_hello


Теперь можно использовать mypackage в коде
import mypackage

print(mypackage.say_hello()) # Выведет: Привет, мир!


🚩Как установить стороннюю библиотеку?

Чтобы установить готовую библиотеку из PyPI, используем pip
pip install requests  # Установка библиотеки requests


Чтобы посмотреть установленные пакеты
pip list


Чтобы удалить пакет
pip uninstall requests


Чтобы обновить пакет
pip install requests --upgrade


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
🤔 В чём сходства и отличия dataclass и namedtuple?

Сходства:
- Оба предоставляют компактный синтаксис для создания объектов с полями.
- Поддерживают доступ по имени (obj.field).
- Иммутабельность (frozen=True для dataclass, по умолчанию в namedtuple).
Отличия:
- namedtuple — неизменяемый, лёгкий и быстрый, но не поддерживает методы, наследование и типизацию так же гибко.
- dataclass — более гибкий, позволяет использовать методы, наследование, значения по умолчанию, валидацию и другие параметры (frozen, order, repr, init и т.д.).


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔2
🤔 Что такое хранитель (Memento)?

Это поведенческий паттерн проектирования, который позволяет сохранять и восстанавливать предыдущее состояние объекта без нарушения инкапсуляции. Этот паттерн особенно полезен для реализации операций отмены и повтора, так как он позволяет хранить состояния объектов и возвращать их к этим состояниям по необходимости.

🚩Зачем нужен?

🟠Сохранение состояния:
Позволяет сохранять текущее состояние объекта и восстанавливать его позже.
🟠Инкапсуляция:
Обеспечивает сохранение состояния объекта без нарушения его инкапсуляции. Внутренние детали объекта остаются скрытыми от других объектов.
🟠Отмена и повтор операций:
Поддерживает функциональность отмены и повтора операций, так как позволяет возвращать объект к предыдущим состояниям.
Пример реализации
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`:
Восстанавливает предыдущее состояние редактора из истории.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8