Python Academy
259 subscribers
5 photos
1 link
По всем вопросам и коммерческим предложениям писать @LadanovNick

Чат студентов Python Academy
https://t.me/pythonacademychat
Download Telegram
Channel created
try/except: ловим ошибки красиво 🚨
Когда приложение встречает неожиданные данные или «ломается» внешний сервис, — незакрытые исключения превращают всё в Traceback. С парой правильных конструкций Python можно превратить «красный экран ужаса» в контролируемое сообщение или план B.

🔹 Что такое try/except?
try — это блок кода, где «может пойти не так».
except — ловушка, которая перехватывает указанное исключение и решает, что делать дальше (залогировать, вернуть дефолт, повторить попытку).

🔸 Базовый синтаксис

try:
result = int(input("Введите число: "))
# пользователь мог ввести «abc»
except ValueError as err:
print("Нужно было число! ", err)

Если int() выбросит ValueError, то except поймает его и программа продолжит жить.

🔹 Несколько исключений — одна обработка

try:
price = float(raw_price)
# при значении «12,34» — ошибка
discount = price / qty
# qty может быть 0
except (ValueError, ZeroDivisionError) as err:
print("Проверьте ввод ➡️", err)

Скобки позволяют задать кортеж типов.

🔹 else и finally: дополнительные возможности

try:
conn = db.connect()
data = conn.fetch("SELECT * FROM users")
except db.DatabaseError as e:
logger.error("База недоступна: %s", e)
else:
# выполнится ТОЛЬКО если исключения не было
process(data)
finally:
# выполнится ВСЕГДА
conn.close()

• else — место для логики, которая нужна только при успехе.
• finally — гарантированное «уборочное» действие (закрыть файл, соединение).

Когда применять try/except
🔹Работа с файлами, сетью, БД: внешние ресурсы ненадёжны.
🔹Парсинг пользовательского ввода или JSON из API.
🔹Конвертация типов (str → int/float) и потенциально «хрупкие» операции.
🔹Интеграция сторонних библиотек, где вы не контролируете внутренний код.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥32👍2
sorted() vs .sort(): когда применять тот или иной вариант ↕️
Python предоставляет два способа упорядочить данные: встроенную функцию sorted() и метод списка .sort(). Ниже — краткое сравнение и рекомендации по использованию.

Основные различия
1️⃣ sorted(iterable)
• Не изменяет исходный объект 
• Возвращает новый отсортированный объект 
• Принимает любой итерируемый (списки, строки, кортежи, генераторы)

2️⃣ list.sort()
• Сортирует список in-place (данные изменяются) 
• Возвращает None 
• Работает только со списками и экономит память, поскольку не создаёт копию

Пример
nums = [3, 1, 4, 1, 5]

sorted_nums = sorted(nums)
# → [1, 1, 3, 4, 5]
print(nums)
# исходный остаётся: [3, 1, 4, 1, 5]

nums.sort()
# сортировка на месте
print(nums)
# → [1, 1, 3, 4, 5]

Общие параметры
🔹 key= — функция, определяющая порядок сортировки (напр. sorted(words, key=len))
🔹 reverse=True — сортировка по убыванию
🔹 Обе операции стабильные: элементы с одинаковым key сохраняют первоначальный порядок

Критерии выбора
🔹Требуется сохранить исходные данные без изменений → sorted()
🔹Нужно упорядочить не-list (строку, tuple, генератор) → sorted()
🔹Работа ведётся с крупным списком, важна экономия памяти → .sort()
🔹Планируется многократная пересортировка одного и того же списка → .sort()
🔹Сортировка встроена в цепочку выражений или генераторов → sorted()

⚠️ Особенности
🔹Метод .sort() всегда возвращает None; использование его результата в присваивании вызовет ошибку.
🔹При применении sorted() к очень большим коллекциям объём используемой памяти увеличивается, поскольку создаётся копия.
🔹Обе реализации основаны на алгоритме Timsort со средней сложностью O(N log N).

📌 Вывод
sorted() обеспечивает неизменность исходных данных и работает с любыми итерируемыми объектами. .sort() выполняет сортировку быстрее и экономнее по памяти, но только для списков и за счёт изменения объекта на месте. Используйте тот вариант, который соответствует конкретным требованиям задачи.
👍63🔥3
This media is not supported in the widget
VIEW IN TELEGRAM
👍7🦄4🔥3
@property: геттеры-сеттеры «по-питоновски»
@property превращает обычные методы в «прозрачные» атрибуты. Класс продолжает выглядеть как работа с полями, но внутри можно валидировать входные данные, кэшировать результаты или менять реализацию — без изменения внешнего интерфейса.

🔹 Что делает @property
1️⃣ Позволяет объявить геттер — метод, который вызывается при чтении атрибута.
2️⃣ Через @<имя>.setter добавляется сеттер для записи.
3️⃣ При необходимости можно добавить @<имя>.deleter для удаления атрибута.

🔸 Мини-пример

class Rectangle:
def __init__(self, w, h):
# вызовет setter
self.width = w
self.height = h

# ---- width ----
@property
def width(self):
return self._w

@width.setter
def width(self, v):
if v <= 0:
raise ValueError('> 0')
self._w = v

# ---- area (read-only) ----
@property
def area(self):
return self.width * self.height

Клиенту класса всё равно, что внутри есть логика: доступ идёт как к «обычному» полю.

Преимущества
🔹Инкапсуляция без шума. Проверки и вычисления скрыты, интерфейс лаконичный.
🔹Совместимость. Можно заменить публичное поле на property, не меняя вызовов в коде.
🔹Ленивая инициализация и кэш. Первый вызов рассчитывает значение, а setter/делитер управляют кэшем.

⚠️ Нюансы
🔹Логика в property должна оставаться быстрой; тяжёлые операции лучше вызывать явно.
🔹Сеттер обязателен, если атрибут нужно менять; без него объект станет «только для чтения».

Когда использовать
🔹Необходимо валидировать входные данные при присвоении.
🔹Значение должно вычисляться на лету (площадь, кэшированное представление).
🔹Планируется изменить внутреннее хранилище данных, сохранив старый API.
👍4🔥21
Python Academy
This media is not supported in the widget
VIEW IN TELEGRAM
5😢3🔥1
5 вопросов, которые почти наверняка зададут на Python-собеседовании 🧩
Ниже — короткая шпаргалка в стиле «вопрос → суть ответа → мини-пример». Сохраните пост, чтобы повторить перед интервью.

🔹 list vs tuple
Что спросят: «чем отличаются и зачем нужен кортеж?»

# list — изменяем
a = [1, 2]; a.append(3)

# tuple — неизменяем
b = (1, 2, 3)

# может быть ключом dict
hash(b)

list изменяем, поэтому занимает больше памяти и не может быть ключом словаря. tuple неизменяем, легче и хэшируем — hash((1,2,3)) работает.

🔹 *args и **kwargs
Что спросят: «Как работает распаковка и порядок параметров?»

def demo(a, *args, z=0, **kw):
print(a, args, z, kw)

demo(1, 2, 3, z=4, x=5)
# → 1 | (2, 3) | 4 | {'x': 5}

*args собирает все дополнительные позиционные аргументы в кортеж, а **kwargs — именованные в словарь.
В сигнатуре сначала идут обычные параметры, затем *args, потом именованные с значениями по умолчанию и в конце **kwargs.

🔹 yield vs return
Что спросят: «Чем генератор лучше обычной функции?»

def squares(n):
for i in range(n):
yield i * i

yield приостанавливает функцию, сохраняя её состояние, поэтому следующая итерация продолжается с того же места.
Генератор выдаёт элементы по запросу, экономя память и позволяя обрабатывать большие потоки данных.

🔹 Почему += со строками медленный?
Что спросят: «Где здесь проблема неизменяемости?»

# неэффективно
s = ''
for w in words:
# каждая конкатенация создаёт новую строку
s += w

# эффективно
s = ''.join(words)

str неизменяем, поэтому при каждом += создаётся новая копия и суммарная сложность растёт до O(n²).
Накопите части в списке и соедините их одним ''.join() — это линейно по времени и памяти.

🔹 GIL и многопоточность
Что спросят: «Почему потоки не ускоряют CPU-bound код в CPython?»
GIL (Global Interpreter Lock) позволяет выполнять байт-код
только одному потоку CPython в любой момент времени.
Поэтому CPU-bound задачи не параллелятся потоками, а для параллели
используют multiprocessing, C-расширения или I/O-ориентированный asyncio.
👍4🔥31
os.path.join и Pathlib: кросс-платформенные пути 🛣️

Когда скрипт должен работать и в Windows, и в Linux, ручная склейка "/" или "\\" быстро приводит к багам. Используйте встроенные инструменты, которые сами подставят нужный разделитель.

Почему это важно ❗️
Пути к файлам отличаются:
🔹Windows → C:\data\file.txt
🔹Linux/Mac → /home/user/file.txt
os.path.join() и pathlib.Path автоматически подставляют правильный разделитель и избегают двойных «//» или «\».

🔸 os.path.join — «старый надёжный»

import os

folder = 'data'
name = 'report.csv'

path = os.path.join('C:\\tmp', folder, name)
print(path)
# Windows: C:\tmp\data\report.csv

Берёт любое количество частей и склеивает безопасно.

🔹 Pathlib — «современный» и удобный

from pathlib import Path

# /home/<user> или C:\Users\<user>
base = Path.home()
path = base / 'data' / 'report.csv'
print(path)


⚠️ Подводные камни
🔹 Не склеивайте пути через + или f-строки — это ломается на другой ОС.
🔹 В os.path.join если одна часть начинается с ведущего «/» или диска (C:\), все предыдущие игнорируются.
🔹 В Path оператор / работает только между объектами Path и/или строками, но не с числами — приведите к str.

Когда применять
🔹 Пишете скрипт, который будут запускать коллеги на разных ОС.
🔹 Строите сложные вложённые пути: base / 'raw' / date / 'file.parquet'.
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍3🔥2
Опубликовали разбор 2 задач из собеседования на аналитика данных в Яндекс 🔥

Статья:
https://vc.ru/hr/2069090-analiticheskie-zadachi-yandeksa
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥32👍2