В Python счетчик ссылок (reference count) используется для управления памятью. Он показывает, сколько раз объект используется в программе. Когда счетчик ссылок падает до нуля, Python автоматически удаляет объект, освобождая память.
Python использует автоматическое управление памятью, основанное на подсчёте ссылок. Когда создаётся объект, Python хранит специальное число — количество ссылок на этот объект. Это число увеличивается, когда мы создаём новую ссылку на объект, и уменьшается, когда удаляем или перезаписываем переменную.
import sys
a = [1, 2, 3] # Создаём список
print(sys.getrefcount(a)) # Выведет 2 (одна ссылка 'a' + вызов getrefcount)
b = a # Новая ссылка на тот же объект
print(sys.getrefcount(a)) # Теперь 3 (a, b и сам getrefcount)
del a # Удаляем одну ссылку
print(sys.getrefcount(b)) # Теперь 2
del b # Удаляем последнюю ссылку, объект будет удалён из памяти
Python сам удаляет ненужные объекты, не давая памяти переполняться.
Если объект имеет циклические ссылки (например, список ссылается сам на себя), Python не может освободить его сразу, поэтому дополнительно используется сборщик мусора (Garbage Collector, GC).
import gc
class Node:
def __init__(self):
self.ref = self # Циклическая ссылка!
n = Node()
del n # Обычный подсчёт ссылок не сработает, объект останется в памяти
gc.collect() # Явный вызов сборщика мусора удалит его
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Да, можно. Декоратор может изменить или вернуть новый класс, обёрнутый в дополнительную логику.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6💊1
Это такие типы данных, которые имеют постоянное (неизменяемое) хеш-значение на протяжении всего времени их существования. Это означает, что их можно использовать в качестве ключей в словарях (
dict) и элементов в множествах (set), так как они поддерживают вычисление хеша с помощью функции 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
Образ собирается из Dockerfile при помощи команды сборки. В процессе выполнения создаются слои, соответствующие каждой инструкции в Dockerfile. По завершении формируется итоговый образ, который можно запускать как контейнер.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
C++ быстрее Python, потому что:
C++ — компилируемый язык, а Python — интерпретируемый.
C++ работает ближе к "железу", а Python использует абстракции.
C++ использует статическую типизацию, а Python динамическую (дополнительные проверки замедляют код).
Простой пример: сложение чисел в цикле
Python (медленно)
import time
start = time.time()
s = 0
for i in range(10_000_000):
s += i
end = time.time()
print("Python:", end - start, "сек")
Результат
Python: 0.8 сек
C++ (быстро)
#include <iostream>
#include <chrono>
int main() {
auto start = std::chrono::high_resolution_clock::now();
long long s = 0;
for (int i = 0; i < 10000000; i++) {
s += i;
}
auto end = std::chrono::high_resolution_clock::now();
std::cout << "C++: "
<< std::chrono::duration<double>(end - start).count()
<< " сек" << std::endl;
}
Результат
C++: 0.05 сек
Они написаны на C/C++ и работают очень быстро. Пример:
numpy.sum(arr) быстрее, чем sum(list), потому что работает на C. Python код пишется в 2-5 раз быстрее, чем C++. Важно для стартапов и прототипов.
Например, парсинг HTML, обработка логов, работа с API.
Игры, графика (
Unreal Engine, Unity, CryEngine). Разработка операционных систем (Windows, Linux). Быстрая обработка данных, алгоритмы (
sorting, graph, machine learning). Например, если нужно перемножить матрицы размером 10 000 × 10 000, C++ справится в разы быстрее. Python слишком медленный для реального времени, а C++ используется в Arduino, автопилотах, микроконтроллерах.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Всё в Python — объекты: числа, строки, функции, классы. Есть поддержка инкапсуляции, наследования, полиморфизма и создания собственных классов.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥3
Рекурсия — это мощный инструмент, но в Python она имеет ограничения, которые нужно учитывать при написании кода.
В 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)
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3💊3🔥1
В Python существует множество структур данных, которые предоставляют различные способы хранения и управления данными. Они делятся на два основных типа: встроенные структуры данных и пользовательские структуры данных (созданные программистом). Встроенные структуры данных предоставляют готовые инструменты для решения большинства задач, а пользовательские разрабатываются вручную для более сложных или специфичных случаев.
К ним относятся те типы данных, которые изначально встроены в Python. Они обеспечивают простое и удобное управление данными. Вот основные типы:
Массив, который может содержать элементы разных типов. Динамический (размер меняется), упорядоченный (элементы хранятся в порядке добавления).
my_list = [1, "hello", 3.14]
print(my_list[1]) # "hello"
Похож на список, но неизменяемый. Используется для данных, которые не должны быть изменены.
my_tuple = (10, 20, 30)
print(my_tuple[0]) # 10
Неупорядоченная коллекция уникальных элементов. Удобно для работы с множествами (поиск пересечений, объединений и т.д.).
my_set = {1, 2, 3, 2}
print(my_set) # {1, 2, 3}Хранит пары ключ-значение. Очень эффективен для быстрого поиска данных по ключу.
my_dict = {"name": "Alice", "age": 25}
print(my_dict["name"]) # AliceЭти структуры создаются с помощью классов или других механизмов, доступных в Python. Они применяются для решения задач, которые не могут быть эффективно выполнены встроенными средствами.
Принцип работы: LIFO (последним пришел — первым ушел). Реализуется через список или
collections.deque. stack = []
stack.append(10) # Добавление
stack.append(20)
print(stack.pop()) # Удаление последнего элемента (20)
Принцип работы: FIFO (первым пришел — первым ушел). Реализуется через
collections.deque или библиотеку queue. from collections import deque
queue = deque()
queue.append(10)
queue.append(20)
print(queue.popleft()) # 10
Элементы связаны друг с другом через указатели. Гибче массивов, но сложнее в реализации.
class Node:
def __init__(self, data):
self.data = data
self.next = None
class LinkedList:
def __init__(self):
self.head = None
def append(self, data):
if not self.head:
self.head = Node(data)
else:
current = self.head
while current.next:
current = current.next
current.next = Node(data)
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
С помощью системных команд, которые показывают список всех процессов с их идентификаторами, статусами, именами и потреблением ресурсов.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊32🤔8
Многопоточность в Python реализуется с помощью модуля
threading, но из-за GIL (Global Interpreter Lock) потоки не могут выполняться параллельно на нескольких ядрах. Модуль
threading позволяет запускать несколько потоков (threads) в одном процессе. import threading
import time
def task(name):
print(f"{name} начал работу")
time.sleep(2) # Имитация задержки
print(f"{name} завершил работу")
# Создаём два потока
t1 = threading.Thread(target=task, args=("Поток 1",))
t2 = threading.Thread(target=task, args=("Поток 2",))
t1.start()
t2.start()
t1.join()
t2.join()
print("Все потоки завершены")
Вывод
Поток 1 начал работу
Поток 2 начал работу
(пауза 2 секунды)
Поток 1 завершил работу
Поток 2 завершил работу
Все потоки завершены
В отличие от
threading, модуль multiprocessing создаёт отдельные процессы, которые могут выполняться на разных ядрах процессора. import multiprocessing
import time
def task(name):
print(f"{name} начал работу")
time.sleep(2)
print(f"{name} завершил работу")
if __name__ == "__main__":
p1 = multiprocessing.Process(target=task, args=("Процесс 1",))
p2 = multiprocessing.Process(target=task, args=("Процесс 2",))
p1.start()
p2.start()
p1.join()
p2.join()
print("Все процессы завершены")
Этот модуль позволяет легко управлять потоками (
ThreadPoolExecutor) и процессами (ProcessPoolExecutor). from concurrent.futures import ThreadPoolExecutor
import time
def task(n):
time.sleep(2)
return f"Готово: {n}"
with ThreadPoolExecutor(max_workers=2) as executor:
results = executor.map(task, [1, 2, 3])
for result in results:
print(result)
Пример
ProcessPoolExecutor (процессы)from concurrent.futures import ProcessPoolExecutor
def square(n):
return n * n
with ProcessPoolExecutor() as executor:
results = executor.map(square, [1, 2, 3, 4])
print(list(results)) # [1, 4, 9, 16]
Модуль
asyncio не создаёт потоки или процессы, а работает через "корутины" и цикл событий (event loop). import asyncio
async def task():
print("Начало")
await asyncio.sleep(2) # Не блокирует другие задачи
print("Конец")
async def main():
await asyncio.gather(task(), task())
asyncio.run(main())
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Плюсы:
- проще начать разработку;
- меньше накладных расходов;
- отладка и деплой проще.
Минусы:
- сложнее масштабировать по частям;
- одно изменение может повлиять на всё приложение;
- трудно разделить работу между командами.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Схема (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
👍8
Позволяют получить подмножество элементов из строки, списка и других последовательностей с помощью синтаксиса [start:stop:step].
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Это небольшой файл, который создаётся веб-сайтом и сохраняется в браузере пользователя. Куки используются для хранения информации, связанной с пользователем, чтобы улучшить его взаимодействие с сайтом.
Куки помогают веб-сайтам «запоминать» данные о пользователе. Вот основные цели их использования:
Например, после входа в аккаунт куки сохраняют ваш статус (авторизован вы или нет).
Куки могут хранить ваши настройки, например, выбранный язык или тему сайта.
Если вы добавляете товары в корзину в интернет-магазине, эта информация может храниться в куки.
Куки используются для аналитики и рекламы, чтобы понять, как вы взаимодействуете с сайтом, или показать персонализированные объявления.
Когда вы заходите на сайт, сервер может отправить куки вашему браузеру вместе с HTTP-ответом.
Браузер сохраняет эти данные и отправляет их обратно на сервер при последующих запросах.
Куки привязаны к домену, и только этот домен может их читать.
Создание куки на сервере (Python, Flask)
from flask import Flask, request, make_response
app = Flask(__name__)
@app.route('/set_cookie')
def set_cookie():
response = make_response("Cookie установлена!")
response.set_cookie('username', 'JohnDoe') # Устанавливаем куки с именем "username"
return response
@app.route('/get_cookie')
def get_cookie():
username = request.cookies.get('username') # Получаем значение куки
return f'Привет, {username}!' if username else 'Куки не найдены.'
if __name__ == '__main__':
app.run(debug=True)
Хранятся только во время работы браузера и удаляются после его закрытия.
Сохраняются на устройстве пользователя до истечения срока действия.
Передаются только через HTTPS для обеспечения безопасности.
Не доступны через JavaScript, используются для защиты от XSS-атак.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🔥2
Можно воспользоваться универсальными функциями для получения всех доступных атрибутов объекта. Это помогает в отладке и динамическом программировании.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔9💊9👍1
Если нужно:
Перехватить исключение
Выполнить какие-то действия (лог, очистка, уведомление и т. д.)
Снова выбросить это же исключение
try:
x = 1 / 0 # Ошибка деления на ноль
except ZeroDivisionError:
print("Ошибка! Записываем в лог...")
raise # Повторно выбрасываем то же исключение
Вывод
Ошибка! Записываем в лог...
Traceback (most recent call last):
File "noscript.py", line 2, in <module>
x = 1 / 0
ZeroDivisionError: division by zero
Пример: Логирование перед повторным выбросом
import logging
logging.basicConfig(filename="errors.log", level=logging.ERROR)
try:
user_input = int("abc") # Ошибка ValueError
except ValueError as e:
logging.error(f"Ошибка: {e}") # Записываем в лог
raise # Повторно выбрасываем исключение
Пример: Очистка ресурсов перед выбросом исключения
try:
file = open("data.txt", "r")
data = file.read()
except FileNotFoundError:
print("Файл не найден. Освобождаем ресурсы...")
raise # Снова выбрасываем исключение
finally:
file.close() # Гарантированно закроет файл
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🤔1
JOIN объединяет строки из двух и более таблиц по общим колонкам (чаще всего по ключам). База находит совпадения и возвращает комбинированный набор данных в соответствии с типом JOIN.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
В Python можно проверять наличие ключа или значения в словаре разными способами.
Самый быстрый и правильный способ — проверять ключи (
keys), так как доступ к ним O(1).data = {"name": "Alice", "age": 25, "city": "New York"}
# Проверяем, есть ли ключ "age"
if "age" in data:
print("Ключ найден!")Вывод
Ключ найден!
Не надо проверять так
if data.get("age") is not None: # ❌ Работает, но `in` быстрееЕсли нужно проверить значение, используем
values()if 25 in data.values():
print("Значение найдено!")
Вывод
Значение найдено!
Если нужно проверить пару (ключ, значение)
if ("age", 25) in data.items():
print("Пара (ключ, значение) найдена!")Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3💊1
С помощью инструкции, которая немедленно завершает цикл и выходит из него, независимо от условия.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊17🤔8👍1
В Django встроена мощная система аутентификации, которая отвечает за идентификацию пользователей, управление учетными записями и контроль доступа к различным частям приложения. Она включает регистрацию, вход, выход, проверку прав пользователей и работу с сессиями.
Аутентификация в Django основана на модели пользователя (
User) и механизме сессий. Когда пользователь входит в систему, Django проверяет его учетные данные и создает сессию, сохраняя в ней идентификатор пользователя.Процесс можно разделить на несколько шагов:
Пользователь вводит логин и пароль.
Django проверяет данные через аутентификационный бэкенд.
Если данные верны, Django создает сессию.
При каждом запросе Django проверяет, авторизован ли пользователь.
Django предоставляет встроенную модель пользователя
django.contrib.auth.models.User. Она содержит:username, email, passwordis_staff, is_superuser, is_activedate_joined, last_loginfrom django.contrib.auth.models import User
# Создание пользователя
user = User.objects.create_user(username="admin", password="12345")
user.email = "admin@example.com"
user.save()
# Проверка пароля
print(user.check_password("12345")) # True
Django использует функцию
authenticate() для проверки учетных данных.from django.contrib.auth import authenticate
user = authenticate(username="admin", password="12345")
if user is not None:
print("Успешный вход!")
else:
print("Ошибка аутентификации!")
После успешной аутентификации пользователя можно "впустить" с помощью
login().from django.contrib.auth import login, logout
def user_login(request):
user = authenticate(username="admin", password="12345")
if user:
login(request, user) # Создает сессию
return "Пользователь вошел!"
return "Ошибка входа"
def user_logout(request):
logout(request) # Удаляет сессию
return "Пользователь вышел!"
Во вьюхах можно проверить, авторизован ли пользователь
if request.user.is_authenticated:
print("Пользователь залогинен:", request.user.username)
else:
print("Гость")
Для защиты маршрутов можно использовать декоратор
@login_required:from django.contrib.auth.decorators import login_required
@login_required
def profile(request):
return "Это страница профиля!"
Django по умолчанию использует
django.contrib.auth.backends.ModelBackend для аутентификации через базу данных. Можно добавить кастомные бэкенды:AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend', # Обычная аутентификация
]
Если стандартной модели
User недостаточно, можно создать кастомную модельfrom django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
phone_number = models.CharField(max_length=15, unique=True)
# В settings.py указываем свою модель
AUTH_USER_MODEL = "myapp.CustomUser"
Django поддерживает группы пользователей и права доступа.
if user.has_perm("app_name.permission_codename"):
print("У пользователя есть разрешение!")Использование групп
from django.contrib.auth.models import Group
group = Group.objects.create(name="Editors") # Создаем группу
user.groups.add(group) # Добавляем пользователя в группу
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3💊1