Точка входа в программирование
18K subscribers
1.77K photos
293 videos
4 files
3.36K links
Фундаментальные знания по основам программирования

Разместить рекламу: @tproger_sales_bot

Правила общения: https://tprg.ru/rules

Другие каналы: @tproger_channels

Сайт: https://tprg.ru/site

Регистрация в перечне РКН: https://tprg.ru/zrgj
Download Telegram
Как CI получает доступ к облаку без пароля в настройках

Классическая схема: в переменных CI лежит ключ от облака, сборка его читает и загружает артефакты. Ключ живёт годами, его копируют в новые проекты, и утечка одного ключа открывает всё. Именно так в августе через непропатченный TeamCity вынесли облачные учётки самой JetBrains, мы разбирали этот инцидент.

Альтернатива называется OIDC, и её теперь поддерживает и TeamCity. Идея простая. Сервер CI получает пару ключей: приватным подписывает, публичный выкладывает по известному адресу. Каждой сборке он выдаёт короткий подписанный документ, JWT, где написано, какой это проект и для какого облака. Сборка показывает документ облаку, облако скачивает публичный ключ, проверяет подпись и выдаёт временный доступ. У TeamCity документ, запрошенный сборкой по HTTP, живёт 5 минут; выданный при старте сборки действует до её таймаута плюс 10 минут.

В конфигурации при этом нет ни одного секрета, только правило «сборкам проекта X можно роль Y». Так же работают GitHub Actions и GitLab CI. Если хотите понять механизм на схеме и увидеть, что внутри JWT, разобрали на сайте.

#основы
❤1👍1
Почему строка после await печатается раньше, чем вы ожидали

Вы поставили await перед загрузкой постов, а строка, которая идёт ниже по коду, напечаталась первой. Выглядит как сломанный await, хотя это ровно его штатная работа.

В Python time.sleep() блокирует всё, и следующая строка честно ждёт. В JavaScript await ставит на паузу только ту функцию, внутри которой стоит, а остальной код бежит дальше. Разбор написал дата-сайентист, который учит JavaScript и объясняет промисы через привычный ему Python: промис здесь объект, который обещает вернуть значение позже.

Скопируйте пример себе и предскажите порядок вывода до запуска, а потом сверьтесь. Ошиблись — значит, нашли своё главное заблуждение о промисах. Пример целиком.

#javascript
❤1
Что делать, если ключ от сервиса уехал в публичный репозиторий

Поздний вечер, код наконец заработал, git add ., коммит, пуш. Через несколько минут расход по API растёт, появляются запросы, которых вы не делали, а счёт больше ожидаемого.

Первый порыв, стереть строчку и закоммитить заново, не спасает: старый коммит остаётся в истории репозитория, и ключ достают оттуда. Поэтому чистка истории идёт не первым шагом, а после того, как ключ отозван и выпущен новый.

Разбор проходит порядок действий целиком, включая удаление секрета из уже опубликованных коммитов. А чтобы не возвращаться к этому, заведите привычку: перед первым пушем нового проекта убедитесь, что .env лежит в .gitignore.

#основы
❤2
Чем интерпретатор отличается от JIT и почему интерпретаторы всё ещё нужны

Два самых распространённых способа исполнять программу. Интерпретатор читает инструкции по одной и выполняет каждую сам, как переводчик на переговорах. JIT-компилятор сначала переводит горячий участок в машинный код процессора, а потом запускает его напрямую, и это в разы быстрее. Браузерные движки сочетают оба: начинают с интерпретатора и переводят в машинный код только горячие участки, это называют tiered execution.

Зачем тогда интерпретаторы? JIT нужно право записывать в память исполняемый код, а на iOS и в некоторых защищённых средах это запрещено. Ему нужна память под скомпилированный код, которой нет на микроконтроллере. И его результат зависит от машины, а смарт-контрактам и песочницам нужен одинаковый результат везде.

Хороший пример того, как далеко можно разогнать интерпретатор, вышел на этой неделе: Wasmi 2.0, интерпретатор WebAssembly на Rust, стал в 2,2 раза быстрее предыдущей версии за счёт того, как устроен цикл выбора инструкций и как хранятся промежуточные значения. Что такое dispatch и аккумуляторные регистры простыми словами, разобрали на сайте.

#основы
🆒1
В документации Python появилась таблица, сколько стоит каждая операция со списком и словарём

Почему l.pop() дешёвый, а l.pop(0) нет, и чем x in set отличается от x in list: раньше за этим ходили в вики или исходники CPython. В документации 3.16 появилась отдельная страница со сложностью операций для list, tuple, dict, set, str и range в нотации O-большое.

Половина вопросов «почему тормозит» на собеседованиях закрывается этой таблицей. В нашем канале Zen of Python разобрали подробнее.

#python #основы
❤4
«Нужно много памяти и быстрый процессор или хорошая видеокарта» — это два разных требования

Хиллел Уэйн выложил вторую главу своей книги Logic for Programmers бесплатно. Он начинает с предикатов, функций, которые возвращают да или нет, и показывает, как фразу из ТЗ превратить в формулу: CanRunProgram(c) = RAM(c) && CPU(c) || GPU(c). Тут же видно, что фраза двусмысленна: (RAM && CPU) || GPU или RAM && (CPU || GPU). В русском предложении этого не заметить, в формуле нельзя не заметить.

Дальше импликация, множества и кванторы «для всех» и «существует», всё на примерах из кода и с упражнениями с ответами. Символы автор берёт с клавиатуры: &&, ||, !, =>, без математических значков. Если формальная логика в университете прошла мимо, это самое короткое введение, после которого требования к программе начинаешь читать иначе.

#основы
❤2
Соберите первую нейросеть на Python без матана и видеокарты

Слово «нейросеть» звучит так, будто нужен продвинутый матанализ, мощная машина и тысячи строк кода. Ничего из этого не нужно.

На базовом уровне нейросеть это математическая модель, которая берёт на вход числа, что-то с ними считает, выдаёт предсказание, сравнивает его с правильным ответом и подправляет себя, чтобы в следующий раз ошибиться меньше. Этот цикл и есть обучение, всё остальное надстраивается сверху.

В туториале такую сеть строят руками на Python и NumPy, без фреймворков, чтобы был виден каждый шаг. Хороший следующий шаг после основ языка: слова «слой», «веса» и «обучение» перестанут быть заклинаниями и станут строчками кода, которые вы написали сами.

#python
❤3
Что делать, когда файл с данными не открывает даже ноутбук

Файл на несколько сотен миллионов строк, просьба «просто быстро посчитай сумму по регионам», спиннер на десять минут и упавшая программа. Дело не в вопросе, а в попытке сделать работу сотни компьютеров на одном.

Apache Spark — движок, который режет одну большую задачу на куски, считает их на многих машинах одновременно и собирает ответ обратно. PySpark это его питоновский интерфейс: вы пишете обычный на вид Python, а параллельная работа происходит под капотом.

Разбор без диссертации рассчитан минут на тринадцать и ведёт от «что это вообще такое» до первой работающей задачи на PySpark, вместе с ловушками, в которые попадают новички. Открывайте его в тот момент, когда pandas на вашем файле начнёт задыхаться.

#python
❤‍🔥2
Словарь это массив, хеш-функция и план на случай, когда два ключа попали в одну ячейку

Автор собирает хеш-таблицу на Rust с нуля, чтобы показать, почему словари и HashMap быстрые и где они ломаются. Первая версия проста: hash(key) % capacity даёт индекс в массиве. Она тут же ломается на коллизии: в таблице на 16 ячеек «Bananas» и «Eggs» попадают в один слот, и второе значение затирает первое.

Классический ответ, список в каждой ячейке, работает, но разбрасывает узлы по памяти и промахивается мимо кеша процессора. Поэтому автор реализует линейное пробирование: если ячейка занята, идём в следующую по кругу. Дальше видно, почему таблицу приходится перестраивать, когда она заполняется, и почему вставка в словарь иногда внезапно дорогая. Код короткий, Rust знать не обязательно, идея переносится на dict в Python и Map в JavaScript.

#основы
❤2👍1
Разнесите разросшуюся проверку по цепочке маленьких обработчиков

В каждом проекте однажды заводится функция, которую никто не хочет трогать. Начиналось с одной проверки, потом добавили if, потом ещё один, а сверху появился комментарий «не менять, не прочитав целиком». Новичков о ней предупреждают на онбординге.

Паттерн Chain of Responsibility, цепочка обязанностей, разбирает такой ком на части. Вместо одного метода, который знает всё, вы строите цепочку обработчиков: каждый знает ровно одно правило и решает, пропустить запрос дальше или остановить прямо здесь. Ни один обработчик не знает ни длины цепочки, ни того, кто стоит до и после него.

Возьмите свою самую разросшуюся проверку и попробуйте выделить из неё два независимых правила. Разбор паттерна покажет, как связать их в цепочку так, чтобы добавление третьего не требовало трогать первые два.
❤3👍1
Достаньте точный цвет пикселя из картинки прямо в браузере

Задача звучит просто: есть скриншот или логотип, нужен точный HEX конкретного пикселя. Обычно за этим идут в графический редактор, хотя браузер умеет сам, и загружать картинку никуда не надо.

Работает это через Canvas — элемент HTML, на котором можно рисовать и, что важнее, читать нарисованное по пикселям. Порядок такой: загрузить изображение, нарисовать его на canvas, забрать массив пикселей и достать нужный. В массиве каждый пиксель занимает четыре числа: красный, зелёный, синий и прозрачность.

Упражнение хорошо тем, что за один маленький проект вы трогаете объект Image, события загрузки и типизированные массивы. Возьмите код примера и соберите пипетку, которая показывает цвет под курсором.

#javascript
❤2
У вас есть широта и долгота: что с ними делать, кроме метки на карте

Пара чисел вроде 40.7128 и −74.0060 обычно заканчивается маркером на карте, и на этом всё. А достать из неё можно заметно больше: найти заведения рядом, определить город и район, посчитать расстояние до другой точки.

Для новичка это удобная тренировка работы с внешним API: отправить запрос с координатами, получить JSON, разобрать его и показать результат. Заодно всплывают вещи, о которых туториалы обычно молчат: что делать, если сервис ничего не нашёл, и почему расстояние по прямой не равно расстоянию пешком.

Разбор на JavaScript годится как основа для маленького проекта «что рядом со мной»: одна форма, один запрос, один список результатов.

#javascript
❤2
Чем ИИ-агент отличается от чат-бота, если объяснять по-человечески

Привычная картина: вы задаёте вопрос, модель отвечает, вы задаёте следующий. Умный и быстрый помощник, который включается, когда к нему обратились, и молчит в остальное время.

Агентный ИИ устроен иначе: он планирует, решает и действует сам. Разницу в статье показывают на заказе командировки. Чат-бот расскажет, как купить билет. Агент разбивает задачу на шаги, идёт по ним по очереди и сам обращается к внешним сервисам.

Разобраться в этом стоит до того, как возьмётесь собирать что-то на API моделей: обзор объясняет, как агент устроен внутри, где такое уже применяют и какие риски приходят вместе с самостоятельностью.

#ии
❤1👍1
JSON.parse на ответе модели работает ровно до четырёхсотого запроса

Большинство туториалов про вызов языковой модели заканчиваются строчкой JSON.parse(response.content). На первом десятке тестов она работает. Потом модель придумывает дату, возвращает восемь элементов массива там, где по схеме допустимо пять, или отдаёт валидный JSON, в котором тихо не хватает поля.

Автор наткнулся на это, делая инструмент для резюме: на вход приходят двухколоночные PDF, таблицы, которые не совсем таблицы, и даты примерно в четырнадцати форматах, а на выходе нужны строгие поля, потому что их сразу видит человек.

Разбор целиком про слой между «модель вернула текст» и «приложению есть чему доверять»: три способа ограничить вывод, почему схему стоит спроектировать раньше, чем удлинять промпт, и как устроить повторный запрос, который не сожжёт бюджет.

#ии
❤1👍1
Разложите по полочкам четыре места, где живёт ваш файл в Git

Git следит за изменениями в проекте, чтобы можно было откатиться назад и увидеть, что именно менялось. Новички обычно заучивают три команды подряд и не понимают, зачем их три, если хватило бы одной.

Смысл в том, что файл проходит четыре места. Рабочий каталог — обычная папка на диске, где вы правите app.py. Область подготовки, она же staging, это витрина: туда вы кладёте только те изменения, которые войдут в следующий коммит, командой git add app.py или git add . для всех сразу. Коммит записывает подготовленное в локальную историю, а git push отправляет её на GitHub.

Проверьте на своём проекте: поправьте два файла, добавьте в staging только один и вызовите git status. Они окажутся в разных списках, и это лучший ответ на вопрос, зачем нужен промежуточный шаг. Разбор с командами.

#основы
❤1
Forwarded from Zen of Python
В Python шесть предобъявленных констант, и каждая ведёт себя по-своему

True, False, None, __debug__, Ellipsis и NotImplemented. Автор разбирает, чем они отличаются, и различий больше, чем ожидаешь.

Первая тройка это вообще не идентификаторы, а собственные лексические токены: разрешаются в лексере, а не при обычном разрешении имён. Побочный эффект в том, что выражение x.True даёт SyntaxError, и больше в языке так не ведёт себя ничего.

Отдельный случай __debug__: обычный идентификатор, но единственный, которому нельзя присвоить значение, причём даже как атрибуту. При этом x.__debug__ даёт уже AttributeError, потому что синтаксически это законно. Хорошая заметка на вечер, если любите тёмные углы языка.
❤1
Forwarded from Zen of Python
Что выбрать под неизменяемые объекты: обычный класс или dataclass

Обычный класс порождает изменяемые экземпляры, пока вы явно не запретите менять атрибуты. Отсюда и вопрос, который разбирает автор: где для неизменяемых данных проходит граница между ручным классом и dataclass.

В разборе три части: как сделать неизменяемость на голом классе, что даёт __slots__ для памяти и контроля атрибутов, и что из этого закрывает dataclass(frozen=True) без ручной работы.

Тема из тех, где каждый однажды принимает решение по привычке и живёт с ним годами. Хороший повод пересмотреть привычку на конкретных примерах.
❤1
Почему добавленный индекс иногда не ускоряет запрос

«Добавь индекс, и станет быстрее» — фраза, которую слышит каждый новичок. Не обязательно: индекс занимает место на диске, замедляет запись и требует поддержки при каждом изменении данных.

Поэтому проектирование начинается с одного вопроса: какие запросы приложение на самом деле выполняет. Не какие могло бы, а какие реально идут в базу. Разбор сначала объясняет, за счёт чего индекс вообще ускоряет выборку, и только потом переходит к чтению своих запросов.

Возьмите свой учебный проект и выпишите пять самых частых запросов, прежде чем создавать первый индекс. Половина вопросов отпадёт сама.
❤1
Почему шифровать по-новому советуют сейчас, хотя квантового компьютера ещё нет

Криптография, которая сегодня защищает ваши ключи, HTTPS и подписи, опирается на задачи, которые обычные компьютеры не решают за разумное время. Достаточно большой квантовый компьютер часть из них решит. Постквантовая криптография это алгоритмы, устойчивые и к тем и к другим.

Возражение напрашивается: такого компьютера пока нет, значит, можно подождать. Мешает атака «собери сейчас, расшифруй потом»: противник записывает ваш шифрованный трафик сегодня и лежит с ним, пока не появится возможность его вскрыть.

Отсюда правило, которое стоит запомнить в начале пути: если данные должны остаться тайной через десять лет, угроза уже настоящая, а не будущая. Разбор объясняет это без математики.
❤1
Рекурсия становится понятной, если разбирать её на связном списке

Автор честно пишет, что структуры данных на C++ дались ему тяжелее всего за год, и дольше прочего не давалась именно связка связных списков с рекурсией.

Половину сложности объясняет разница с массивом. В массиве всё лежит рядом в памяти, и элемент берётся по индексу. В связном списке каждый узел хранит значение и указатель на следующий: чтобы добраться до пятого, надо пройти через четыре предыдущих.

Именно эта пошаговость и делает список удобным для рекурсии: функция обрабатывает текущий узел и передаёт следующий сама себе. Разбор с кодом стоит сначала повторить на бумаге, а потом уже запускать.
❤1
Почему одна модель выдаёт то 45, то 793 токена в секунду

Токены в секунду это универсальный спидометр локальных моделей: цифру приводят в каждом бенчмарке и каждом обзоре видеокарты. И это одно из самых обманчивых чисел в области.

Разброс не опечатка. Та же модель показывает 45 или 793 токена в секунду в зависимости от условий замера, и главный фактор — конкурентность: бенчмарк на одного пользователя и нагрузка на десяток запросов дают принципиально разные числа.

Разбор объясняет, что такое токен, почему число так пляшет и как читать чужой бенчмарк, не обманывая себя. Полезно до того, как выбирать железо по чужим графикам.
❤1