Программистика
قناة بسيطة
Лучший канал про python Ссылка для друга: https://t.me/+Ai6ughKtf5g2ZmFi Купить рекламу: https://telega.in/c/+Ai6ughKtf5g2ZmFi Админ: @JeyRahol По рекламе: @ReivuManager
إظهار المزيد5 571
المشتركون
-324 ساعات
+67 أيام
+4930 أيام
أرشيف المشاركات
5 572
⏰ Работа с датами и временем в Python: как не сойти с ума с часовыми поясами и форматами
Каждый разработчик хотя бы раз сталкивался с магией, когда дата внезапно смещается на день, или время отображается не так, как ожидалось. А если добавить часовые пояса, летнее время и странные форматы из API — голова идёт кругом. Разбираемся, как правильно работать с датами, чтобы код не подводил.
🧱 Почему это сложно: проблема времени
Время — это не просто число. Есть:
🟢 Локальное время (зависит от часового пояса).
🟢 UTC (единый стандарт).
🟢 Unix timestamp (секунды с 1970 года).
🟢 Форматы (ISO, RFC, пользовательские).
🟢 Переход на летнее время (DST).
🟢 Часовые пояса с разными смещениями.
Python предлагает несколько модулей:
datetime, time, calendar, а с Python 3.9+ — zoneinfo для работы с часовыми поясами.
📦 Основные инструменты
1. `datetime` — главный модуль
from datetime import datetime, date, time, timedelta, timezone
# Текущее время
now = datetime.now() # локальное
now_utc = datetime.now(timezone.utc) # UTC
# Создание даты
d = date(2024, 12, 31)
t = time(14, 30, 0)
dt = datetime(2024, 12, 31, 14, 30, 0)
# Разница между датами
delta = timedelta(days=5, hours=3)
new_date = dt + delta
2. `time` — низкоуровневые функции
import time
timestamp = time.time() # Unix timestamp (секунды с 1970)
3. `zoneinfo` — часовые пояса (Python 3.9+)
from zoneinfo import ZoneInfo
tz_moscow = ZoneInfo("Europe/Moscow")
dt_moscow = datetime.now(tz_moscow)
📝 Парсинг и форматирование
`strptime` — строка → дата
from datetime import datetime
date_str = "2024-12-31 14:30:00"
dt = datetime.strptime(date_str, "%Y-%m-%d %H:%M:%S")
`strftime` — дата → строка
formatted = dt.strftime("%d.%m.%Y %H:%M")
print(formatted) # 31.12.2024 14:30
ISO-формат (встроено)
iso_str = dt.isoformat() # 2024-12-31T14:30:00
dt_from_iso = datetime.fromisoformat(iso_str)
🌍 Часовые пояса: `naive` vs `aware`
- Naive — без информации о часовом поясе. Это просто локальное время.
- Aware — с информацией о смещении от UTC.
# naive
naive = datetime.now()
# aware
aware = datetime.now(timezone.utc)
aware_moscow = aware.astimezone(ZoneInfo("Europe/Moscow"))
Правило: всегда храните время в UTC, конвертируйте при выводе в нужный часовой пояс.
🧪 Пример: работа с API
Допустим, вы получаете дату в формате "2024-12-31T14:30:00Z" (ISO с Z — UTC).
from datetime import datetime
# парсим
dt = datetime.fromisoformat("2024-12-31T14:30:00Z".replace('Z', '+00:00'))
# конвертируем в московское время
moscow = dt.astimezone(ZoneInfo("Europe/Moscow"))
print(moscow.strftime("%d.%m.%Y %H:%M")) # 31.12.2024 17:30
🧪 Полезные методы
# Начало дня
start_of_day = dt.replace(hour=0, minute=0, second=0, microsecond=0)
# Конец дня
end_of_day = dt.replace(hour=23, minute=59, second=59, microsecond=999999)
# День недели (0 = понедельник)
weekday = dt.weekday()
# Добавление дней
next_week = dt + timedelta(days=7)
# Unix timestamp
ts = dt.timestamp()
dt_from_ts = datetime.fromtimestamp(ts, tz=timezone.utc)
⚠️ Ловушки и частые ошибки
1. Забыть про `timezone.utc` при создании `now()` — получится naive объект.
2. Сравнивать naive и aware — TypeError. Всегда приводите к общему знаменателю.
3. Забыть про DST (летнее время) — при переходе на летнее время в некоторых странах время смещается. zoneinfo учитывает это.
4. Парсить строки без явного формата — используйте ISO или чётко задавайте %Y-%m-%d.
5. Хранить время в локальном времени в БД — храните UTC, а при отображении конвертируйте.
💡 Запомни:
Даты и время — не враги, если понимать правила. Главное — хранить UTC, конвертировать при выводе, использовать zoneinfo для часовых поясов и всегда быть внимательным к форматам.
Программистика|| #Статья5 572
🧠 Загадка на ночь: что выведет этот код?
def create_counter():
count = 0
def inner():
nonlocal count
count += 1
return count
return inner
counters = [create_counter() for _ in range(3)]
results = [counter() for counter in counters]
print(results)
Варианты:
1. [1, 1, 1]
2. [1, 2, 3]
3. [3, 3, 3]
4. Ошибка
Пиши свой вариант в комментарии! Ответ и разбор — через пару часов 🔥
Программистика|| #quiz5 572
❤️🔥"Это лютый сетап, бро!" 😤
Так сказал мой друг из Африки, когда увидел этот стол)
Не знаю уж че за сетап, меня зовут Саша и качественную необычную мебель из натурального дерева я делаю уже больше 12-ти лет, столько же занимаюсь и темой здоровья.
Когда я услышал, что до 10% смертности связано с сидячим образом жизни, меня это поразило и я задался целью делать максимально функциональные и полезные рабочие пространства, ибо геморрой в 30 это конечно довольно нишево, но все же сомнительно 😂
Ну а собрать такой комплект под свои задачи и при этом сразу прикинуть цены вы можете в удобном Mini App конструкторе
5 572
⚡️ Айтишник из «VISION» скупил курсы айти школ и выложил гигабайты материалов к себе
Каждый найдет что-то по душе:
1202 ГБ — Python
1811 ГБ — Frontend
1100 ГБ — C / C++ / C#
804 ГБ — Java
411 ГБ — SQL & БД
309 ГБ — DevOps
998 ГБ — ИБ & Хакинг
773 ГБ — Kotlin / Swift
189 ГБ — PHP
201 ГБ — GoLang
170 ГБ — Rust
167 ГБ — QA / Тестирование
310 ГБ — 1C + Лицензии
495 ГБ — Машинное обучение
704 ГБ — Аналитика Данных
991 ГБ — Дизайн
Материалы в закрепе, постоянно пополняются👆🏻
5 572
5 572
🖥 Archy — это архитектурный сенсор для Python-кодовых баз, который следит за структурой проекта и не даёт ей «гнить» под нагрузкой AI-кода. Он строит граф зависимостей модулей в реальном времени и выдаёт единую оценку архитектурного здоровья, показывает циклические зависимости, точки для рефакторинга и модули, которые меняются чаще всего. Работает в CI, pre-commit и как MCP-сервер для AI-агентов.Установка:
pip install archy.
Программистика||#Репозиторий5 572
💻 Логово Сфинкса - одно из самых активных ИБ-комьюнити во всём телеграме!
Сам Сфинкс очень умелый молодой ИБ специалист
И на своём канале он освещает такие темы, как:
— атаки на актив директори
— атаки на инфру
— обход различных средств защиты и фишинг
— C2 Фреймворки
— И много опыта из жизни и работы
Посуди сам:
🐈⬛ Дорожная карта со стажёра до мидла
🐈⬛ О важности методологии в ИБ
🐈⬛ Переиграли мошенника и угнали его акк
Так же он помогает своим подписчикам обучиться ИБ и грамотно войти в профессию не тратясь на бесполезные курсы
Подпишись чтобы стать классным спецом👍
5 572
📌 Секрет
operator.itemgetter: сортируй словари без лямбд
Сортировка списка словарей по ключу — частая задача. Многие пишут lambda x: x['key'], но есть более читаемый и быстрый способ.
❌ Было (лямбда):
users = [{'name': 'Боб', 'age': 30}, {'name': 'Алиса', 'age': 25}]
sorted_users = sorted(users, key=lambda x: x['age'])
✔️ Стало (operator.itemgetter):
from operator import itemgetter
sorted_users = sorted(users, key=itemgetter('age'))
itemgetter работает быстрее лямбды и читается как «возьми значение по ключу». Можно передавать несколько ключей для сортировки по нескольким полям:
sorted_users = sorted(users, key=itemgetter('age', 'name'))
Для объектов используйте attrgetter:
from operator import attrgetter
sorted_users = sorted(users, key=attrgetter('age'))
🟢 Запомни: itemgetter и attrgetter — твои помощники для чистого и быстрого кода.
Программистика|| #tips5 572
📦 Итераторы: что скрывается за `for` и как написать свой
Каждый день вы пишете
for x in list:, но задумывались ли вы, как это работает? Цикл for не знает ничего о списках, кортежах или словарях. Он знает только про итераторы. Именно итераторы обеспечивают единообразие обхода любых коллекций в Python. Разбираемся, как это устроено и как написать свой итератор.
🧱 Что такое итератор и зачем он нужен
Итератор — это объект, который поддерживает протокол итерации: метод __iter__() (возвращает сам себя) и метод __next__() (возвращает следующий элемент или бросает StopIteration). Когда вы пишете for x in obj:, Python вызывает iter(obj), затем многократно вызывает next() до исключения.
# Что делает for под капотом
it = iter(my_list)
while True:
try:
x = next(it)
# тело цикла
except StopIteration:
break
🧠 Создаём свой итератор
Допустим, вы хотите итерироваться по числам Фибоначчи, но не хотите хранить их все в списке. Пишем свой итератор.
class FibonacciIterator:
def __init__(self, limit):
self.limit = limit
self.a = 0
self.b = 1
self.count = 0
def __iter__(self):
return self
def __next__(self):
if self.count >= self.limit:
raise StopIteration
result = self.a
self.a, self.b = self.b, self.a + self.b
self.count += 1
return result
for num in FibonacciIterator(10):
print(num) # 0, 1, 1, 2, 3, 5, 8, 13, 21, 34
⚡️ `iter` и `next` в действии
lst = [1, 2, 3]
it = iter(lst)
print(next(it)) # 1
print(next(it)) # 2
print(next(it)) # 3
print(next(it)) # StopIteration
Итератор одноразовый. После исчерпания его нельзя использовать повторно.
🧩 Итерируемые объекты vs Итераторы
- Итерируемый объект (Iterable) — у него есть метод __iter__(), который возвращает итератор.
- Итератор (Iterator) — у него есть __iter__() (возвращает себя) и __next__().
# Список — итерируемый, но не итератор
lst = [1, 2, 3]
print(iter(lst)) # <list_iterator object at 0x...>
print(next(lst)) # TypeError: 'list' object is not an iterator
# Итератор — и итерируемый, и итератор
it = iter(lst)
print(iter(it) is it) # True
📌 Встроенные итераторы
- range() — итератор (ленивый, не хранит все числа).
- enumerate() — итератор.
- zip() — итератор.
- map(), filter() — итераторы.
# Все они ленивые — не хранят данные, пока не пройдёшь
r = range(1_000_000) # 0 байт
lst = list(r) # 8 МБ
🧪 Итератор для бесконечной последовательности
class InfiniteCounter:
def __init__(self, start=0):
self.current = start
def __iter__(self):
return self
def __next__(self):
result = self.current
self.current += 1
return result
counter = InfiniteCounter()
for _ in range(10):
print(next(counter)) # 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
⚠️ Ловушки и ограничения
1. Итератор можно использовать только один раз — после исчерпания он перестаёт работать.
it = iter([1, 2, 3])
print(list(it)) # [1, 2, 3]
print(list(it)) # []
2. Не все итерируемые объекты поддерживают `len()` — итераторы не знают свою длину.
3. Не путайте итератор с генератором — генератор — это частный случай итератора, создаваемый через yield. Генератор проще писать, но он менее гибкий для сложной логики.
4. Итератор не может быть скопирован — состояние хранится внутри.
💡 Запомни:
🟢 Итератор — это объект с __iter__() и __next__(). Он выдаёт элементы по одному. 🟢 Итерируемый объект — это объект, у которого есть __iter__(), возвращающий итератор. 🟢 for работает с любым итерируемым объектом — для списков, строк, файлов, генераторов. 🟢 Итератор одноразовый — после исчерпания его нельзя использовать повторно. 🟢 Встроенные функции range(), enumerate(), zip(), map(), filter() возвращают итераторы.Программистика|| #Статья
5 572
🖥 tzlocal — это модуль на языке Python, предназначенный для определения локального часового пояса системы и предоставления соответствующего объекта tzinfo!
🐱 Ссылка на GitHub
Программистика|| #Репозиторий
5 572
🖥 tzlocal — это модуль на языке Python, предназначенный для определения локального часового пояса системы и предоставления соответствующего объекта tzinfo!
🐱 Ссылка на GitHub
Программистика|| #Репозиторий
5 572
Пишешь на Python и задумываешься о повышении грейда? А уверен, что потянешь?
Есть способ проверить себя — не дожидаясь реального собеседования.
Кирилл Коданев — Senior Python-разработчик, который сам проводит собеседования. За плечами 17 офферов — среди них Avito, Т-Банк, X5. Он собрал тест-собеседование по Python: 15 вопросов на каждый грейд, от Intern до Senior.
И это не просто вопросы — а именно те, на которых чаще всего валят на интервью. Не нагенеренные нейронкой, а реальные: Кирилл отобрал их сам, потому что точно знает, что и зачем спрашивают.
Один из них, для примера:
Почему list.append() — это амортизированная O(1), хотя иногда Python копирует весь массив целиком?Знаешь ответ — отлично. Нет — тебе точно сюда. Пройдёшь за ~10 минут и получишь: ⏺ свой реальный грейд и вилку зарплаты под него ⏺ темы, которые проседают (пока есть время подтянуть) ⏺ разбор каждого ответа лично от Кирилла Тест бесплатный, доступен по ссылке. P.S. У него же в канале — вся правда про найм в IT: что скрывают рекрутеры, как узнать реальную зарплату в вакансии и почему тебя не зовут на собесы.
5 572
⚡️ Секрет `functools.cache`: запоминай результаты одной строкой
Устали писать словарь для кэширования результатов функции? В Python 3.9+ есть встроенный декоратор, который делает это автоматически.
from functools import cache
@cache
def fib(n):
if n < 2:
return n
return fib(n-1) + fib(n-2)
print(fib(100)) # Мгновенно
@cache — это как @lru_cache(maxsize=None), только короче. Идеально для чистых функций, которые часто вызываются с одинаковыми аргументами.
🟢 Запомни: cache автоматически запоминает результаты вызовов. Не пишите свои кэши вручную.
Программистика|| #tips5 572
🧠 Отгадка: что выведет этот код?
def func(x):
x = x + [1]
return x
a = [0]
b = func(a)
print(a, b)
✅ Правильный ответ: 1. `[0] [0, 1]`
📖 Почему так происходит?
Внутри функции func выполняется x = x + [1]. Это конкатенация, которая создаёт новый список, а не изменяет существующий. Переменная x становится локальной и указывает на новый объект [0, 1], а исходный список a остаётся нетронутым.
Если бы мы использовали x.append(1), то изменили бы исходный список, и ответ был бы [0, 1] [0, 1]. Но здесь — создание нового объекта через +, поэтому a не меняется.
Ключевой момент: + для списков возвращает новый объект, а += или append() изменяют существующий.
Программистика|| #quiz5 572
🧩 `functools.partial`: заморозь аргументы и получи новую функцию
Вы когда-нибудь ловили себя на том, что передаёте одну и ту же функцию с одними и теми же аргументами в несколько мест? Или хотите создать специализированную версию существующей функции без переписывания кода?
functools.partial — это инструмент, который "замораживает" часть аргументов функции, создавая новую функцию с меньшим количеством параметров. Идеально для колбэков, адаптеров и упрощения кода.
from functools import partial
def power(base, exponent):
return base ** exponent
square = partial(power, exponent=2)
cube = partial(power, exponent=3)
print(square(5)) # 25
print(cube(5)) # 125
Где реально пригодится:
- GUI-колбэки: когда обработчик требует функцию без аргументов, а вам нужно передать данные.
- Сортировка с параметрами: заморозить key для sorted().
- API-клиенты: зафиксировать базовый URL или заголовки.
- map/filter: когда нужно передать функцию с дополнительными параметрами.
# Пример с сортировкой
from operator import mul
double = partial(mul, 2)
print(list(map(double, range(5)))) # [0, 2, 4, 6, 8]
# Пример с колбэком
def log(level, message):
print(f"[{level}] {message}")
info = partial(log, "INFO")
error = partial(log, "ERROR")
info("Сервер запущен") # [INFO] Сервер запущен
error("Ошибка сети") # [ERROR] Ошибка сети
💡 Запомни: partial — не магия, а удобный способ уменьшить дублирование и сделать код чище. Работает с любыми функциями, методами и даже классами.
Программистика|| #doc5 572
👩💻 FastAPI — Разбираем популярные вопросы с собеседований
📱 ПервоисточникПрограммистика|| #video
