Гринатом — ИТ-интегратор Росатома — ищет системного архитектора АРМ в Москве!💼
✅Вам предстоит разрабатывать архитектурные концепции и технические решения на АРМ, готовить презентации и обоснования архитектурных решений, проводить аудит и анализ текущей инфраструктуры, разрабатывать стратегии миграции на отечественные платформы и участвовать в разработке проектной документации.
🤝А мы предложим конкурентоспособную «белую» зарплату с годовыми бонусами и ежегодной индексацией, ДМС со стоматологией, тренажерный зал с сауной в офисе, образовательные курсы за счёт компании. И главное — карьерный и экспертный рост в рамках единой команды.
✅Вам предстоит разрабатывать архитектурные концепции и технические решения на АРМ, готовить презентации и обоснования архитектурных решений, проводить аудит и анализ текущей инфраструктуры, разрабатывать стратегии миграции на отечественные платформы и участвовать в разработке проектной документации.
🤝А мы предложим конкурентоспособную «белую» зарплату с годовыми бонусами и ежегодной индексацией, ДМС со стоматологией, тренажерный зал с сауной в офисе, образовательные курсы за счёт компании. И главное — карьерный и экспертный рост в рамках единой команды.
hh.ru
Вакансия Системный архитектор АРМ в Москве, работа в компании Гринатом. Бэк-офис
Зарплата: не указана. Москва. Требуемый опыт: 3–6 лет. Полная. Дата публикации: 02.11.2025.
🔥1
This media is not supported in your browser
VIEW IN TELEGRAM
BBOT (Black Box OSINT Toolkit)
Рекурсивный модульный OSINT инструмент, написанный на Python.
Он поддерживает модульную структуру, интеграцию с API и плагины для выполнения сетевых сканирований, анализа доменов, поиска утечек данных и других задач. BBOT нацелен на исследование целевых систем, обеспечивая гибкость и настраиваемость для профессионалов в области кибербезопасности.
https://github.com/blacklanternsecurity/bbot
Мы в MAX
👉@BookPython
Рекурсивный модульный OSINT инструмент, написанный на Python.
Он поддерживает модульную структуру, интеграцию с API и плагины для выполнения сетевых сканирований, анализа доменов, поиска утечек данных и других задач. BBOT нацелен на исследование целевых систем, обеспечивая гибкость и настраиваемость для профессионалов в области кибербезопасности.
https://github.com/blacklanternsecurity/bbot
Мы в MAX
👉@BookPython
👍1
Если вы хотите игнорировать какое-то исключение, вы, вероятно, сделаете что-то вроде этого:
Это будет работать (ничего не выводя), но
📲 Мы в MAX
👉@BookPython
try:
lst = [1, 2, 3, 4, 5]
print(lst[10])
except IndexError:
pass
Это будет работать (ничего не выводя), но
contextlib позволяет сделать то же самое более выразительно и семантически правильно:
from contextlib import suppress
with suppress(IndexError):
lst = [1, 2, 3, 4, 5]
lst[10]
👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Media is too big
VIEW IN TELEGRAM
Как использовать *args и **kwargs в python?
В видео про декораторы мы использовали
📲 Мы в MAX
👉@BookPython
В видео про декораторы мы использовали
*args и **kwargs для того, чтобы передать в функцию любое количество позиционных и именованных аргументов. Для того, чтобы понять как это работает, сначала познакомимся с тем, что такое распаковка.👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2💊2
Распаковка параметров функций в Python 2 и 3
В Python 2 существовала интересная возможность распаковывать параметры функций прямо в их определении. Пример:
Более того, это работало даже рекурсивно:
Но начиная с Python 3, эта возможность была удалена из языка. Чтобы добиться того же результата, теперь нужно распаковывать параметры вручную:
Удаление этой функциональности сделало код более явным и читаемым, но для любителей компактности Python 2 по-прежнему вызывает лёгкую ностальгию.
📲 Мы в MAX
👉@BookPython
В Python 2 существовала интересная возможность распаковывать параметры функций прямо в их определении. Пример:
def between(x, (start, stop)):
return start < x < stop
interval = (5, 10)
print(between(2, interval)) # False
print(between(7, interval)) # True
Более того, это работало даже рекурсивно:
def determinant_2_x_2(((a, b), (c, d))):
return a * d - c * b
matrix = [
(1, 2),
(3, 4),
]
print(determinant_2_x_2(matrix)) # -2
Но начиная с Python 3, эта возможность была удалена из языка. Чтобы добиться того же результата, теперь нужно распаковывать параметры вручную:
def determinant_2_x_2(matrix):
row1, row2 = matrix
a, b = row1
c, d = row2
return a * d - c * b
matrix = [
(1, 2),
(3, 4),
]
print(determinant_2_x_2(matrix)) # -2
Удаление этой функциональности сделало код более явным и читаемым, но для любителей компактности Python 2 по-прежнему вызывает лёгкую ностальгию.
👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤1
Почему
Функция
Почему полуоткрытые интервалы?
Полуоткрытые интервалы позволяют легко "склеивать" смежные диапазоны без риска ошибок на единицу:
- Если
Это работает идеально, потому что конец одного интервала (`b`) автоматически становится началом следующего.
В случае закрытых интервалов, такая "склейка" требует дополнительной обработки:
Связь с индексацией с нуля
Индексация с нуля в Python также связана с этим принципом. Рассмотрим диапазон
- Этот диапазон включает ровно N элементов, что делает код более предсказуемым:
Здесь
Преимущества для работы с массивами
Полуоткрытые интервалы идеально подходят для работы с индексами массивов:
Интервал
Исторический контекст
Этот подход имеет глубокие корни в компьютерной науке. Эдсгер Дейкстра, один из пионеров программирования, в 1982 году написал блестящую статью, в которой обосновал преимущества полуоткрытых интервалов. Это не просто удобство — это вопрос корректности и простоты работы с данными.
📲 Мы в MAX
👉@BookPython
range() в Python использует полуоткрытые интервалы?Функция
range() в Python работает с полуоткрытыми интервалами. Например, range(2, 10) задаёт числа в диапазоне [2, 10), то есть [2, 3, 4, 5, 6, 7, 8, 9]. На первый взгляд это может показаться неочевидным или асимметричным, но у такого подхода есть свои преимущества.Почему полуоткрытые интервалы?
Полуоткрытые интервалы позволяют легко "склеивать" смежные диапазоны без риска ошибок на единицу:
- Если
a = 2, b = 5, и c = 10, то [a, c) можно выразить как:
[a, c) = [a, b) + [b, c)
Это работает идеально, потому что конец одного интервала (`b`) автоматически становится началом следующего.
В случае закрытых интервалов, такая "склейка" требует дополнительной обработки:
[a, c] = [a, b] + [b+1, c]
Связь с индексацией с нуля
Индексация с нуля в Python также связана с этим принципом. Рассмотрим диапазон
range(0, N):- Этот диапазон включает ровно N элементов, что делает код более предсказуемым:
for i in range(0, N):
print(i)
Здесь
i проходит значения от 0 до N-1, что логично и удобно.Преимущества для работы с массивами
Полуоткрытые интервалы идеально подходят для работы с индексами массивов:
arr = [10, 20, 30, 40, 50]
print(arr[1:3]) # [20, 30]
Интервал
[1:3) охватывает элементы с индексами 1 и 2, но не 3, что упрощает вычисления границ.Исторический контекст
Этот подход имеет глубокие корни в компьютерной науке. Эдсгер Дейкстра, один из пионеров программирования, в 1982 году написал блестящую статью, в которой обосновал преимущества полуоткрытых интервалов. Это не просто удобство — это вопрос корректности и простоты работы с данными.
👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Как узнать размер генератора в Python?
В Python часто возникает задача определить размер генератора без необходимости извлечения всех его значений. Это полезно, если вы работаете с большими потоками данных и хотите избежать избыточного расхода памяти.
Пример с len()
Некоторые итераторы, такие как
Однако генераторы не имеют длины, и попытка вызвать
Стандартное решение: преобразование в список
Один из способов получить размер генератора — это преобразовать его в список:
Этот подход работает, но имеет серьёзный недостаток: он требует загрузить все значения генератора в память. Если генератор очень большой, это может привести к нехватке памяти.
Более эффективный подход: подсчёт с помощью sum
Чтобы избежать лишнего расхода памяти, можно подсчитать количество элементов в генераторе с использованием
Этот метод обходит генератор "лениво", не создавая дополнительных списков, что делает его идеальным для работы с большими потоками данных.
Резюме
- Используйте
- Для генераторов избегайте преобразования в список, если важна экономия памяти.
- Используйте
📲 Мы в MAX
👉@BookPython
В Python часто возникает задача определить размер генератора без необходимости извлечения всех его значений. Это полезно, если вы работаете с большими потоками данных и хотите избежать избыточного расхода памяти.
Пример с len()
Некоторые итераторы, такие как
range, поддерживают вызов len():
len(range(10000)) # 10000
Однако генераторы не имеют длины, и попытка вызвать
len() вызовет ошибку:
gen = (x ** 2 for x in range(10000))
len(gen) # TypeError: object of type 'generator' has no len()
Стандартное решение: преобразование в список
Один из способов получить размер генератора — это преобразовать его в список:
gen = (x ** 2 for x in range(10000))
print(len(list(gen))) # 10000
Этот подход работает, но имеет серьёзный недостаток: он требует загрузить все значения генератора в память. Если генератор очень большой, это может привести к нехватке памяти.
Более эффективный подход: подсчёт с помощью sum
Чтобы избежать лишнего расхода памяти, можно подсчитать количество элементов в генераторе с использованием
sum():
gen = (x ** 2 for x in range(10000))
print(sum(1 for _ in gen)) # 10000
Этот метод обходит генератор "лениво", не создавая дополнительных списков, что делает его идеальным для работы с большими потоками данных.
Резюме
- Используйте
len() только для итераторов, поддерживающих его (например, range).- Для генераторов избегайте преобразования в список, если важна экономия памяти.
- Используйте
sum(1 for _ in gen) для эффективного подсчёта элементов генератора.👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2💩2
Media is too big
VIEW IN TELEGRAM
Прежде чем читать длиннющий релиз новой версии Python 3.14, посмотрите это видео Евгения Афонасьева, тимлида разработки Antifraud в Авито 🚀
За 12 минут он рассказал, какие фичи стоят внимания внедрения в работу, про небольшие, но приятные обновления тоже не забыл.
📺 Смотрим и обсуждаем по ссылке!
За 12 минут он рассказал, какие фичи стоят внимания внедрения в работу, про небольшие, но приятные обновления тоже не забыл.
Please open Telegram to view this post
VIEW IN TELEGRAM
💩2
Когда вам нужно очистить список в Python, вы, скорее всего, используете
Пример:
Хотя это кажется очевидным, правильное решение стало доступно только с введением метода
До этого для очистки списка приходилось использовать:
-
-
Оба варианта работают, поскольку срезы позволяют модифицировать часть списка. Если вы берёте срез
Теперь же
📲 Мы в MAX
👉@BookPython
lst = []. Однако на самом деле вы просто создаёте новый пустой список и присваиваете его переменной lst, а все другие переменные, которые ссылаются на исходный список, продолжают хранить его содержимое. Пример:
lst = [1, 2, 3]
lst2 = lst
lst = []
print(lst2) # [1, 2, 3]
Хотя это кажется очевидным, правильное решение стало доступно только с введением метода
lst.clear() в Python 3.3. До этого для очистки списка приходилось использовать:
-
del lst[:], или -
lst[:] = [].Оба варианта работают, поскольку срезы позволяют модифицировать часть списка. Если вы берёте срез
[:], он охватывает весь список.Теперь же
lst.clear() является более читаемым и современным решением. 👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤2🙏1
Please open Telegram to view this post
VIEW IN TELEGRAM
🤮2👎1💩1
Пагинация — это стандартная задача, с которой ежедневно сталкиваются тысячи разработчиков. Если вы используете реляционную базу данных, то можно задать смещение через
Этот запрос действительно вернет 100 записей, с 1001-й по 1100-ю. Но проблема в том, что для базы данных это так же сложно, как и выборка всех первых 1001 записей. Чем дальше запрашиваемая страница, тем медленнее будет выполняться запрос.
Более оптимальным решением является использование фильтрации через
Этот подход позволяет избежать сканирования всех предыдущих строк, что значительно ускоряет работу с большими объемами данных.
Если хотите разобраться подробнее, рекомендую почитать отличную статью на эту тему!
📲 Мы в MAX
👉@BookPython
LIMIT, например:
SELECT *
FROM table
LIMIT 1001, 100;
Этот запрос действительно вернет 100 записей, с 1001-й по 1100-ю. Но проблема в том, что для базы данных это так же сложно, как и выборка всех первых 1001 записей. Чем дальше запрашиваемая страница, тем медленнее будет выполняться запрос.
Более оптимальным решением является использование фильтрации через
WHERE, где клиент передает идентификатор последней записи текущей страницы ($last_seen_id в примере):
SELECT *
FROM table
WHERE id > $last_seen_id
ORDER BY id ASC
LIMIT 100;
Этот подход позволяет избежать сканирования всех предыдущих строк, что значительно ускоряет работу с большими объемами данных.
Если хотите разобраться подробнее, рекомендую почитать отличную статью на эту тему!
👉@BookPython
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤1