🤔 Как переподнять исключение в блоке except?
Внутри блока except можно использовать ключевое слово raise без аргументов, чтобы повторно выбросить текущее перехваченное исключение. Это полезно, если нужно что-то логировать или изменить, но затем продолжить распространение ошибки.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Внутри блока except можно использовать ключевое слово raise без аргументов, чтобы повторно выбросить текущее перехваченное исключение. Это полезно, если нужно что-то логировать или изменить, но затем продолжить распространение ошибки.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍2
🤔 Встроенные функции Python
В Python есть встроенные функции (built-in functions) — это функции, которые можно использовать без импорта. Они делают код проще и удобнее.
Полный список встроенных функций можно посмотреть так:
🚩Основные категории встроенных функций
Работа с числами
Работа со строками
Работа с коллекциями (списки, кортежи, множества)
Работа с логикой и проверками
Работа с функциями
Работа с файлами
Работа с объектами и атрибутами
Ставь 👍 и забирай 📚 Базу знаний
В Python есть встроенные функции (built-in functions) — это функции, которые можно использовать без импорта. Они делают код проще и удобнее.
Полный список встроенных функций можно посмотреть так:
print(dir(__builtins__))
🚩Основные категории встроенных функций
Работа с числами
print(abs(-5)) # 5
print(round(3.14159, 2)) # 3.14
print(pow(2, 3)) # 8
print(min([3, 1, 4])) # 1
Работа со строками
print(len("hello")) # 5
print(str(123)) # '123'
print(ord('A')) # 65
print(chr(65)) # 'A'Работа с коллекциями (списки, кортежи, множества)
a = [3, 1, 2]
print(sorted(a)) # [1, 2, 3]
nums = [1, 2, 3]
names = ["Alice", "Bob", "Charlie"]
print(list(zip(nums, names))) # [(1, 'Alice'), (2, 'Bob'), (3, 'Charlie')]
Работа с логикой и проверками
print(bool("")) # False
print(all([True, 1, "Hello"])) # True
print(any([0, "", None, 5])) # True (есть хотя бы один True)Работа с функциями
nums = [1, 2, 3, 4]
squared = list(map(lambda x: x**2, nums))
print(squared) # [1, 4, 9, 16]
evens = list(filter(lambda x: x % 2 == 0, nums))
print(evens) # [2, 4]
Работа с файлами
with open("file.txt", "w") as f:
f.write("Hello, world!")
name = input("Введите имя: ")
print("Привет,", name)Работа с объектами и атрибутами
print(type(42)) # <class 'int'>
print(isinstance(42, int)) # True
print(dir([])) # Методы списка
Ставь 👍 и забирай 📚 Базу знаний
👍1
🤔 Что известно об идемпотентности?
Это свойство операции, при котором повторное выполнение даёт тот же результат, что и одноразовое.
В HTTP:
- GET, PUT, DELETE, HEAD, OPTIONS — идемпотентные.
- POST — не идемпотентный, потому что каждое выполнение может создавать новые данные.
Идемпотентность важна для надёжности запросов — например, при повторных вызовах после сетевых сбоев.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
В HTTP:
- GET, PUT, DELETE, HEAD, OPTIONS — идемпотентные.
- POST — не идемпотентный, потому что каждое выполнение может создавать новые данные.
Идемпотентность важна для надёжности запросов — например, при повторных вызовах после сетевых сбоев.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍1
🤔 Почему вычислять большие значения в асинхронной функции плохо?
Асинхронность (
Если в
🚩Асинхронность в Python подходит для ввода-вывода (I/O-bound)
Асинхронность позволяет выполнять задачи без блокировки, но только если они ждут чего-то (файлы, сеть, БД).
🚩Проблема с `async` и тяжёлыми вычислениями (CPU-bound)
Если в
🚩Как правильно выполнять вычисления в `async`?
🟠Использовать `asyncio.to_thread()` (делегирование в потоки)
В Python 3.9+ можно выполнять CPU-задачи в отдельных потоках, не блокируя
🟠Использовать `multiprocessing` (запуск на нескольких ядрах)
Так как Python использует GIL, единственный способ выполнять настоящий параллелизм — это
Ставь 👍 и забирай 📚 Базу знаний
Асинхронность (
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())
Ставь 👍 и забирай 📚 Базу знаний
👍2
🤔 Что такое Docker Daemon?
Docker Daemon (dockerd) — это фоновый процесс, управляющий:
- образами,
- контейнерами,
- сетями и томами.
Он слушает команды от клиента (docker) и взаимодействует с ядром ОС для запуска контейнеров.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Docker Daemon (dockerd) — это фоновый процесс, управляющий:
- образами,
- контейнерами,
- сетями и томами.
Он слушает команды от клиента (docker) и взаимодействует с ядром ОС для запуска контейнеров.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍2
🤔 Какие нюансы есть в использовании чисел как ключей?
Использование чисел в качестве ключей в словарях Python – это достаточно распространённый случай. Однако у этого подхода есть несколько нюансов, которые нужно учитывать для избежания ошибок.
🚩Хешируемость чисел
Ключи в словаре должны быть хешируемыми, поскольку словари в Python основаны на хеш-таблицах. Хешируемость означает, что объект имеет неизменное значение хеша в течение его жизни. Числа (как
🚩Взаимодействие `int` и `float`
Python не делает различий между
🚩Непредсказуемое поведение при работе с `float`
Числа с плавающей запятой (
🚩Производительность
Использование чисел как ключей в словарях эффективно с точки зрения производительности. Поскольку числа хешируются быстро и занимают меньше памяти, операции добавления, удаления и поиска выполняются очень быстро.
🚩Проблемы при преобразованиях
Если ключами словаря являются числа, то при обработке данных (например, чтении из файла или API) можно случайно преобразовать их в строки, что приведёт к созданию новых ключей вместо использования существующих.
🚩Пользовательские объекты с числовыми свойствами
Если вы используете пользовательские объекты как ключи и они ведут себя как числа (например, реализуют методы
Ставь 👍 и забирай 📚 Базу знаний
Использование чисел в качестве ключей в словарях Python – это достаточно распространённый случай. Однако у этого подхода есть несколько нюансов, которые нужно учитывать для избежания ошибок.
🚩Хешируемость чисел
Ключи в словаре должны быть хешируемыми, поскольку словари в Python основаны на хеш-таблицах. Хешируемость означает, что объект имеет неизменное значение хеша в течение его жизни. Числа (как
int, так и float) являются хешируемыми, поэтому их можно использовать в качестве ключей.d = {1: "один", 2: "два"}
print(d[1]) # "один"🚩Взаимодействие `int` и `float`
Python не делает различий между
int и float, если их значения равны. Это связано с тем, что у них одинаковое хеш-значение при равенстве. d = {1: "один", 1.0: "float один", 2: "два"}
print(d) # {1: 'float один', 2: 'два'}🚩Непредсказуемое поведение при работе с `float`
Числа с плавающей запятой (
float) иногда ведут себя непредсказуемо из-за ошибок округления, которые возникают из-за особенностей представления чисел в памяти компьютера.d = {0.1 + 0.2: "значение"} # 0.1 + 0.2 не равно точно 0.3 из-за округления
print(d.get(0.3)) # None, ключ не найден!🚩Производительность
Использование чисел как ключей в словарях эффективно с точки зрения производительности. Поскольку числа хешируются быстро и занимают меньше памяти, операции добавления, удаления и поиска выполняются очень быстро.
🚩Проблемы при преобразованиях
Если ключами словаря являются числа, то при обработке данных (например, чтении из файла или API) можно случайно преобразовать их в строки, что приведёт к созданию новых ключей вместо использования существующих.
d = {1: "один", 2: "два"}
print(d.get("1")) # None, строка "1" и число 1 – это разные ключи!🚩Пользовательские объекты с числовыми свойствами
Если вы используете пользовательские объекты как ключи и они ведут себя как числа (например, реализуют методы
__hash__ и __eq__), то их поведение должно быть совместимо с ожидаемым использованием. class MyNumber:
def __init__(self, value):
self.value = value
def __hash__(self):
return hash(self.value)
def __eq__(self, other):
return self.value == other.value
d = {MyNumber(1): "один"}
print(d[MyNumber(1)]) # "один"
Ставь 👍 и забирай 📚 Базу знаний
🔥1
🤔 Чем отличается re.match от re.search?
- re.match() проверяет только начало строки на соответствие шаблону. Если начало не совпадает — возвращает None.
-re.search () ищет соответствие в любом месте строки и возвращает первое совпадение.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
- re.match() проверяет только начало строки на соответствие шаблону. Если начало не совпадает — возвращает None.
-
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍4
🤔 Чем отличаются методы сокрытия?
Методы и атрибуты класса могут быть скрыты от внешнего использования с помощью различных уровней сокрытия. Сокрытие реализуется с помощью соглашений об именах, а не с помощью жесткой инкапсуляции, как в некоторых других языках программирования. Основные уровни сокрытия включают публичные, защищенные и приватные методы и атрибуты.
🚩Публичные методы и атрибуты
Доступны из любого места, как внутри класса, так и за его пределами. Их имена не начинаются с подчеркиваний.
🚩Защищенные методы и атрибуты
Не предназначены для использования за пределами класса и его подклассов. Они обозначаются одним подчеркиванием в начале имени. Это всего лишь соглашение, сигнализирующее другим разработчикам, что такие методы и атрибуты не следует использовать вне класса или его подклассов.
🚩Приватные методы и атрибуты
Скрыты от внешнего доступа и доступны только внутри самого класса. Они обозначаются двумя подчеркиваниями в начале имени. Python реализует это с помощью механизма именования, который изменяет имя метода или атрибута, добавляя к нему имя класса, чтобы затруднить доступ извне.
Ставь 👍 и забирай 📚 Базу знаний
Методы и атрибуты класса могут быть скрыты от внешнего использования с помощью различных уровней сокрытия. Сокрытие реализуется с помощью соглашений об именах, а не с помощью жесткой инкапсуляции, как в некоторых других языках программирования. Основные уровни сокрытия включают публичные, защищенные и приватные методы и атрибуты.
🚩Публичные методы и атрибуты
Доступны из любого места, как внутри класса, так и за его пределами. Их имена не начинаются с подчеркиваний.
class MyClass:
def __init__(self):
self.public_attribute = "I am public"
def public_method(self):
return "This is a public method"
obj = MyClass()
print(obj.public_attribute) # Вывод: I am public
print(obj.public_method()) # Вывод: This is a public method
🚩Защищенные методы и атрибуты
Не предназначены для использования за пределами класса и его подклассов. Они обозначаются одним подчеркиванием в начале имени. Это всего лишь соглашение, сигнализирующее другим разработчикам, что такие методы и атрибуты не следует использовать вне класса или его подклассов.
class MyClass:
def __init__(self):
self._protected_attribute = "I am protected"
def _protected_method(self):
return "This is a protected method"
class SubClass(MyClass):
def access_protected(self):
return self._protected_method()
obj = MyClass()
sub_obj = SubClass()
print(sub_obj.access_protected()) # Вывод: This is a protected method
🚩Приватные методы и атрибуты
Скрыты от внешнего доступа и доступны только внутри самого класса. Они обозначаются двумя подчеркиваниями в начале имени. Python реализует это с помощью механизма именования, который изменяет имя метода или атрибута, добавляя к нему имя класса, чтобы затруднить доступ извне.
class MyClass:
def __init__(self):
self.__private_attribute = "I am private"
def __private_method(self):
return "This is a private method"
def access_private(self):
return self.__private_method()
obj = MyClass()
try:
print(obj.__private_attribute)
except AttributeError as e:
print(e) # Вывод: 'MyClass' object has no attribute '__private_attribute'
try:
print(obj.__private_method())
except AttributeError as e:
print(e) # Вывод: 'MyClass' object has no attribute '__private_method'
# Доступ к приватным методам через публичный метод класса
print(obj.access_private()) # Вывод: This is a private method
Ставь 👍 и забирай 📚 Базу знаний
👍1
🤔 Срезы или слайсы в Python?
Позволяют получить подмножество элементов из строки, списка и других последовательностей с помощью синтаксиса [start:stop:step].
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Позволяют получить подмножество элементов из строки, списка и других последовательностей с помощью синтаксиса [start:stop:step].
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍3
🤔 Как отсортировать список словарей по определенному полю?
Для сортировки списка словарей по определенному полю в Python удобно использовать функцию sorted() или метод sort(). Оба подхода позволяют указать ключ сортировки с помощью параметра key, где можно передать либо функцию, либо лямбда-выражение, которое извлекает значение из словаря для сортировки.
🚩Почему это важно?
Списки словарей часто используются для хранения структурированных данных. Например, вы можете иметь список сотрудников, где каждый сотрудник представлен в виде словаря с полями, такими как имя, возраст и зарплата. Сортировка по определенному полю позволяет упорядочить данные, чтобы ими было проще пользоваться или отображать.
🚩Как это сделать?
🟠Использование функции `sorted()`
Эта функция возвращает новый отсортированный список.
Результат
🟠Использование метода `sort()`
Этот метод изменяет существующий список.
Результат
🟠Сортировка в обратном порядке
Установите параметр reverse=True, чтобы отсортировать в порядке убывания.
🟠Использование функции `itemgetter` из модуля `operator`
Это более эффективный способ, чем лямбда-функция, особенно для больших данных.
🚩Обработка отсутствующих значений
Если поле может отсутствовать в некоторых словарях, можно использовать параметр key для обработки таких ситуаций.
Результат
Ставь 👍 и забирай 📚 Базу знаний
Для сортировки списка словарей по определенному полю в Python удобно использовать функцию sorted() или метод sort(). Оба подхода позволяют указать ключ сортировки с помощью параметра key, где можно передать либо функцию, либо лямбда-выражение, которое извлекает значение из словаря для сортировки.
🚩Почему это важно?
Списки словарей часто используются для хранения структурированных данных. Например, вы можете иметь список сотрудников, где каждый сотрудник представлен в виде словаря с полями, такими как имя, возраст и зарплата. Сортировка по определенному полю позволяет упорядочить данные, чтобы ими было проще пользоваться или отображать.
🚩Как это сделать?
🟠Использование функции `sorted()`
Эта функция возвращает новый отсортированный список.
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}]Ставь 👍 и забирай 📚 Базу знаний
👍2
🤔 Как в обычном tuple происходит обращение?
В обычном tuple доступ к элементам осуществляется только по индексу
Обычные кортежи не имеют имён полей, и их нельзя использовать как именованные структуры без дополнительных обёрток.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
В обычном tuple доступ к элементам осуществляется только по индексу
Обычные кортежи не имеют имён полей, и их нельзя использовать как именованные структуры без дополнительных обёрток.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
🤔 Как происходит наследование моделей в Django?
В Django можно наследовать модели, используя стандартное наследование классов. Это помогает повторно использовать код, организовывать данные и добавлять общие поля в несколько моделей. Django поддерживает три основных типа наследования:
🟠Абстрактные модели
Абстрактные модели используются, когда нужно создать базовый класс с полями и методами, которые должны быть унаследованы, но сам класс не должен создавать таблицу в базе данных.
Создается базовый класс с
Дочерние классы наследуют его поля и методы, но не его саму в виде отдельной таблицы.
🟠Многоуровневое (конкретное) наследование
Этот тип наследования создаёт отдельные таблицы для каждой модели. Используется, когда дочерний класс должен представлять отдельную сущность, но при этом иметь доступ к полям родительского класса.
Django создаёт отдельные таблицы в БД для родительской и дочерней модели.
Дочерняя модель автоматически получает
🟠Прокси-модели (Proxy Models)
Используются, когда нужно изменить поведение модели без изменения структуры базы данных.
Прокси-модель наследует поля родительской модели.
В
Можно переопределять методы, добавлять новые, но не менять поля.
Ставь 👍 и забирай 📚 Базу знаний
В Django можно наследовать модели, используя стандартное наследование классов. Это помогает повторно использовать код, организовывать данные и добавлять общие поля в несколько моделей. Django поддерживает три основных типа наследования:
🟠Абстрактные модели
Абстрактные модели используются, когда нужно создать базовый класс с полями и методами, которые должны быть унаследованы, но сам класс не должен создавать таблицу в базе данных.
Создается базовый класс с
abstract = True в Meta.Дочерние классы наследуют его поля и методы, но не его саму в виде отдельной таблицы.
from django.db import models
class BaseModel(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
abstract = True # Указывает, что это абстрактная модель
class Post(BaseModel):
title = models.CharField(max_length=255)
content = models.TextField()
class Comment(BaseModel):
text = models.TextField()
🟠Многоуровневое (конкретное) наследование
Этот тип наследования создаёт отдельные таблицы для каждой модели. Используется, когда дочерний класс должен представлять отдельную сущность, но при этом иметь доступ к полям родительского класса.
Django создаёт отдельные таблицы в БД для родительской и дочерней модели.
Дочерняя модель автоматически получает
OneToOneField на родительскую.class Person(models.Model):
name = models.CharField(max_length=255)
class Employee(Person): # Отдельная таблица employee
salary = models.DecimalField(max_digits=10, decimal_places=2)
🟠Прокси-модели (Proxy Models)
Используются, когда нужно изменить поведение модели без изменения структуры базы данных.
Прокси-модель наследует поля родительской модели.
В
Meta указывается proxy = True.Можно переопределять методы, добавлять новые, но не менять поля.
class Person(models.Model):
name = models.CharField(max_length=255)
class Manager(Person):
class Meta:
proxy = True # Указываем, что это прокси-модель
def get_uppercase_name(self):
return self.name.upper()
Ставь 👍 и забирай 📚 Базу знаний
🔥1
🤔 Что такое Docker container?
Docker container — это запущенный экземпляр образа, изолированный процесс с собственным файловым пространством, сетью и конфигурацией. Контейнеры можно останавливать, перезапускать, удалять и масштабировать.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Docker container — это запущенный экземпляр образа, изолированный процесс с собственным файловым пространством, сетью и конфигурацией. Контейнеры можно останавливать, перезапускать, удалять и масштабировать.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍4🤔1
🤔 Зачем нужен volume в docker?
В Docker
🚩Зачем нужен `volume`?
Данные не теряются при удалении контейнера
Общий доступ: несколько контейнеров могут использовать один и тот же
Производительность: тома быстрее, чем хранение внутри контейнера
Разделение кода и данных: удобно для баз данных и логов
🚩Как создать `volume`?
Способ 1: Автоматическое создание при запуске контейнера
Способ 2: Создать том отдельно и подключить его
Способ 3: Использовать путь на хосте (bind-mount)
🚩Как посмотреть список томов?
🚩Как удалить `volume`?
Важно: при удалении тома данные удаляются безвозвратно!
Ставь 👍 и забирай 📚 Базу знаний
В Docker
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 # Удаление всех неиспользуемых томов
Ставь 👍 и забирай 📚 Базу знаний
🤔 Разница кэш и куки?
- Кэш — это временное хранилище файлов и ответов, чтобы ускорить загрузку (изображения, стили, скрипты, запросы).
- Cookie — это небольшие данные о пользователе, сохраняемые браузером и автоматически передаваемые серверу (например, для авторизации, настроек, корзин).
Кэш ускоряет работу, cookie — хранят состояние пользователя?
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
- Кэш — это временное хранилище файлов и ответов, чтобы ускорить загрузку (изображения, стили, скрипты, запросы).
- Cookie — это небольшие данные о пользователе, сохраняемые браузером и автоматически передаваемые серверу (например, для авторизации, настроек, корзин).
Кэш ускоряет работу, cookie — хранят состояние пользователя?
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍3💊1
🤔 Какие есть виды файловых объектов?
В Python существует несколько типов файловых объектов, которые используются для работы с различными типами данных. Рассмотрим основные виды файловых объектов и их особенности.
🟠Текстовые файлы (`TextIOWrapper`)
Это самый распространённый тип файловых объектов. Такие файлы используются для работы с текстовыми данными и поддерживают строковые операции.
🟠Бинарные файлы (`BufferedReader`, `BufferedWriter`)
Эти файлы используются для работы с двоичными данными (изображениями, видео, аудиофайлами и т. д.).
🟠Файлы ввода-вывода в памяти (`io.StringIO`, `io.BytesIO`)
Эти объекты представляют собой файловые буферы, которые хранят данные в оперативной памяти, а не на диске.
Пример работы с
🟠Файловые объекты на основе сокетов, пайпов и других источников
Python позволяет работать с файловыми объектами, полученными из нестандартных источников, например, сокетов или каналов связи (
Ставь 👍 и забирай 📚 Базу знаний
В Python существует несколько типов файловых объектов, которые используются для работы с различными типами данных. Рассмотрим основные виды файловых объектов и их особенности.
🟠Текстовые файлы (`TextIOWrapper`)
Это самый распространённый тип файловых объектов. Такие файлы используются для работы с текстовыми данными и поддерживают строковые операции.
with open("example.txt", "w", encoding="utf-8") as file:
file.write("Привет, мир!") # Записываем текст в файл
with open("example.txt", "r", encoding="utf-8") as file:
content = file.read() # Читаем текст из файла
print(content)🟠Бинарные файлы (`BufferedReader`, `BufferedWriter`)
Эти файлы используются для работы с двоичными данными (изображениями, видео, аудиофайлами и т. д.).
with open("image.jpg", "rb") as file:
binary_data = file.read() # Читаем файл в бинарном режиме
print(binary_data[:10]) # Выведем первые 10 байтов
with open("copy.jpg", "wb") as file:
file.write(binary_data) # Записываем данные в новый файл🟠Файлы ввода-вывода в памяти (`io.StringIO`, `io.BytesIO`)
Эти объекты представляют собой файловые буферы, которые хранят данные в оперативной памяти, а не на диске.
from io import StringIO
file = StringIO()
file.write("Привет, мир!") # Запись данных в буфер
file.seek(0) # Перемещаем указатель в начало
print(file.read()) # Читаем данные из буфера
Пример работы с
BytesIO:from io import BytesIO
file = BytesIO()
file.write(b"Binary data") # Запись бинарных данных
file.seek(0)
print(file.read()) # Чтение данных
🟠Файловые объекты на основе сокетов, пайпов и других источников
Python позволяет работать с файловыми объектами, полученными из нестандартных источников, например, сокетов или каналов связи (
pipes).import socket
s = socket.socket()
s.connect(("example.com", 80))
s.sendall(b"GET / HTTP/1.1\r\nHost: example.com\r\n\r\n")
response = s.makefile("r", encoding="utf-8") # Создание файлового объекта
print(response.readline()) # Читаем первую строку HTTP-ответа
s.close()
Ставь 👍 и забирай 📚 Базу знаний
👍1
🤔 Какие есть минусы у Monkey Patch если использовать не в тесте?
Monkey Patching — это изменение или замена кода существующих классов и функций во время выполнения программы. Хотя этот метод бывает полезен, особенно в тестировании, его использование в продакшене может привести к опасным и непредсказуемым последствиям
🚩Ломает предсказуемость кода
Когда ты изменяешь поведение встроенных библиотек или сторонних модулей на лету, программисты, читающие код, не смогут понять, почему стандартные функции ведут себя не так, как ожидалось.
🚩Может вызвать неожиданные ошибки после обновления библиотек
Если библиотека обновится, и её внутренняя логика изменится, Monkey Patch может перестать работать или, что ещё хуже, привести к багам.
Ты сделал Monkey Patch метода
🚩Трудно отлаживать и поддерживать
Monkey Patching меняет поведение кода в скрытом режиме, поэтому сложно понять, почему что-то работает не так. Если баг возник из-за патча, отладка может занять часы или даже дни.
Ты исправил баг с
🚩Может затронуть весь код проекта (глобальное изменение)
Monkey Patching меняет поведение для всей программы, а не только в одном модуле или файле. Это делает код хрупким и непредсказуемым.
Если ты изменишь метод
🚩Нет гарантии, что это сработает во всех окружениях
Monkey Patch может работать на одной версии Python или библиотеки, но сломаться на другой. В продакшене, где есть разные серверы и окружения, это может вызвать непредсказуемые ошибки.
Ставь 👍 и забирай 📚 Базу знаний
Monkey Patching — это изменение или замена кода существующих классов и функций во время выполнения программы. Хотя этот метод бывает полезен, особенно в тестировании, его использование в продакшене может привести к опасным и непредсказуемым последствиям
🚩Ломает предсказуемость кода
Когда ты изменяешь поведение встроенных библиотек или сторонних модулей на лету, программисты, читающие код, не смогут понять, почему стандартные функции ведут себя не так, как ожидалось.
import datetime
# Меняем поведение метода now()
def fake_now():
return datetime.datetime(2000, 1, 1)
datetime.datetime.now = fake_now # Monkey Patch
print(datetime.datetime.now()) # Выведет 2000-01-01 00:00:00
🚩Может вызвать неожиданные ошибки после обновления библиотек
Если библиотека обновится, и её внутренняя логика изменится, Monkey Patch может перестать работать или, что ещё хуже, привести к багам.
Ты сделал Monkey Patch метода
json.dumps, а потом библиотека json обновилась и поменяла его сигнатуру. Теперь твой патч сломается или будет работать некорректно. 🚩Трудно отлаживать и поддерживать
Monkey Patching меняет поведение кода в скрытом режиме, поэтому сложно понять, почему что-то работает не так. Если баг возник из-за патча, отладка может занять часы или даже дни.
Ты исправил баг с
str.split(), заменив его через Monkey Patch, но через 6 месяцев разработчик обновил код, забыл про патч, и всё сломалось.🚩Может затронуть весь код проекта (глобальное изменение)
Monkey Patching меняет поведение для всей программы, а не только в одном модуле или файле. Это делает код хрупким и непредсказуемым.
Если ты изменишь метод
dict.get(), он будет вести себя по-другому во всех модулях программы. Это может привести к критическим ошибкам. original_get = dict.get
def patched_get(self, key, default=None):
print(f"Запрашивается ключ: {key}")
return original_get(self, key, default)
dict.get = patched_get # Monkey Patch
d = {"a": 10}
print(d.get("a")) # Работает, но теперь с побочным эффектом
🚩Нет гарантии, что это сработает во всех окружениях
Monkey Patch может работать на одной версии Python или библиотеки, но сломаться на другой. В продакшене, где есть разные серверы и окружения, это может вызвать непредсказуемые ошибки.
Ставь 👍 и забирай 📚 Базу знаний
🤔 Зачем нужны схемы в БД?
Схема (schema) в базе данных — это логическая группировка объектов (таблиц, индексов, представлений и т. д.) внутри одной БД.
🚩Что такое схема в БД?
Схема — это контейнер для объектов БД (таблиц, индексов, процедур).
🚩Как создавать и использовать схемы?
Создание схемы (
Создание таблицы внутри схемы
Выбор схемы по умолчанию
🚩Где полезны схемы?
🟠Разделение данных по модулям
Если в БД хранятся разные области бизнеса (кадры, продажи, финансы), их можно разделить по схемам:
-
-
🟠Разные версии одной БД
Например, в PostgreSQL можно создать схему
-
-
🟠Безопасность и доступ пользователей
Можно дать доступ к разным схемам разным пользователям:
Ставь 👍 и забирай 📚 Базу знаний
Схема (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;
Ставь 👍 и забирай 📚 Базу знаний
🤔 Что такое dict comprehensions?
🚩Простейший пример `dict comprehension`
Вывод
🚩`dict comprehension` с условием (`if`)
Оставляем только чётные числа:
Вывод
🚩Преобразование списка в словарь
Создаём словарь из списка пар (
Вывод
🚩Обратный словарь (ключи и значения меняются местами)
Инвертируем словарь
Вывод
🚩Генерация словаря из `zip()`
Объединяем два списка в словарь
Вывод
🚩`dict comprehension` с `if-else`
Разделяем числа на чётные и нечётные
Вывод
Ставь 👍 и забирай 📚 Базу знаний
dict comprehension (генератор словаря) — это способ быстро создать словарь с помощью компактного синтаксиса, похожего на list comprehension. 🚩Простейший пример `dict comprehension`
squares = {x: x**2 for x in range(1, 6)}
print(squares)Вывод
{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}🚩`dict comprehension` с условием (`if`)
Оставляем только чётные числа:
squares = {x: x**2 for x in range(1, 11) if x % 2 == 0}
print(squares)Вывод
{2: 4, 4: 16, 6: 36, 8: 64, 10: 100}🚩Преобразование списка в словарь
Создаём словарь из списка пар (
name → длина слова) names = ["Alice", "Bob", "Charlie"]
name_lengths = {name: len(name) for name in names}
print(name_lengths)
Вывод
{'Alice': 5, 'Bob': 3, 'Charlie': 7}🚩Обратный словарь (ключи и значения меняются местами)
Инвертируем словарь
{ключ: значение} → {значение: ключ} original = {"a": 1, "b": 2, "c": 3}
inverted = {v: k for k, v in original.items()}
print(inverted)Вывод
{1: 'a', 2: 'b', 3: 'c'}🚩Генерация словаря из `zip()`
Объединяем два списка в словарь
keys = ["name", "age", "city"]
values = ["Alice", 25, "New York"]
person = {k: v for k, v in zip(keys, values)}
print(person)
Вывод
{'name': 'Alice', 'age': 25, 'city': 'New York'}🚩`dict comprehension` с `if-else`
Разделяем числа на чётные и нечётные
numbers = range(1, 6)
parity = {x: "чётное" if x % 2 == 0 else "нечётное" for x in numbers}
print(parity)
Вывод
{1: 'нечётное', 2: 'чётное', 3: 'нечётное', 4: 'чётное', 5: 'нечётное'}Ставь 👍 и забирай 📚 Базу знаний
🤔 Можно ли извлечь элемент генератора по индексу?
Нет, генераторы не поддерживают индексацию. Их элементы можно получить только путём итерации.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Нет, генераторы не поддерживают индексацию. Их элементы можно получить только путём итерации.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
🤔 Как понять, какие виды тестов нужны именно сейчас?
Выбор типа тестирования зависит от целей, стадии разработки и текущих проблем. Чтобы определить, какие тесты нужны, стоит ответить на вопросы:
Что тестируем? (код, API, UI, производительность и т. д.)
Какие риски? (где может сломаться, критичность ошибки)
Какой этап разработки? (новый код, рефакторинг, релиз)
🚩Как определить нужные тесты прямо сейчас?
🟠Только написали новый код
Нужны: Юнит-тесты
Тестируем функции и классы отдельно.
🟠Соединяем модули или работаем с API
Нужны: Интеграционные тесты
Проверяем работу всей системы вместе.
🟠Перед релизом или деплоем
Нужны: Функциональные и регрессионные тесты
Проверяем ключевые сценарии и старый функционал.
🟠Изменили UI (например, фронтенд на React)
Нужны: UI-тесты (Selenium, Playwright)
Проверяем нажатие кнопок, формы и отображение страниц.
🟠Если проект должен выдерживать большую нагрузку
Нужны: Нагрузочные тесты (Load Testing)
Используем
Ставь 👍 и забирай 📚 Базу знаний
Выбор типа тестирования зависит от целей, стадии разработки и текущих проблем. Чтобы определить, какие тесты нужны, стоит ответить на вопросы:
Что тестируем? (код, API, UI, производительность и т. д.)
Какие риски? (где может сломаться, критичность ошибки)
Какой этап разработки? (новый код, рефакторинг, релиз)
🚩Как определить нужные тесты прямо сейчас?
🟠Только написали новый код
Нужны: Юнит-тесты
Тестируем функции и классы отдельно.
def add(a, b):
return a + b
def test_add():
assert add(2, 3) == 5 # ✅ Юнит-тест
🟠Соединяем модули или работаем с API
Нужны: Интеграционные тесты
Проверяем работу всей системы вместе.
def test_api():
response = requests.get("https://api.example.com/data")
assert response.status_code == 200
🟠Перед релизом или деплоем
Нужны: Функциональные и регрессионные тесты
Проверяем ключевые сценарии и старый функционал.
def test_login():
assert login("user", "password") == "Success"
🟠Изменили UI (например, фронтенд на React)
Нужны: UI-тесты (Selenium, Playwright)
Проверяем нажатие кнопок, формы и отображение страниц.
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://example.com")
assert "Example" in driver.title
🟠Если проект должен выдерживать большую нагрузку
Нужны: Нагрузочные тесты (Load Testing)
Используем
locust, JMeter, k6, чтобы проверить сколько пользователей выдержит сервер. from locust import HttpUser, task
class MyUser(HttpUser):
@task
def test_homepage(self):
self.client.get("/")
Ставь 👍 и забирай 📚 Базу знаний