Python: задачки и вопросы
Развёрнутое пояснение:
1. При первом обращении c.ports вызывается метод ports и возвращается список [80].
2. cached_property записывает этот объект в c.__dict__ под именем ports.
3. Вызов c.ports.append(443) изменяет именно тот список, который теперь лежит в кэше.
4. При повторном обращении c.ports cached_property находит ports в __dict__ и возвращает сохранённый объект [80, 443].
5. print выводит [80, 443].
Почему это важно: cached_property удобен для дорогих вычислений, но кэшированный объект остаётся общим для всех последующих обращений. Если метод возвращает изменяемую коллекцию и кто-то её мутирует, изменения застревают в кэше. В конфигах и синглтонах это приводит к «засорению» настроек между тестами или запросами: безопаснее возвращать неизменяемые копии или отделять изменяемое состояние от кэшированного свойства.
2. cached_property записывает этот объект в c.__dict__ под именем ports.
3. Вызов c.ports.append(443) изменяет именно тот список, который теперь лежит в кэше.
4. При повторном обращении c.ports cached_property находит ports в __dict__ и возвращает сохранённый объект [80, 443].
5. print выводит [80, 443].
Почему это важно: cached_property удобен для дорогих вычислений, но кэшированный объект остаётся общим для всех последующих обращений. Если метод возвращает изменяемую коллекцию и кто-то её мутирует, изменения застревают в кэше. В конфигах и синглтонах это приводит к «засорению» настроек между тестами или запросами: безопаснее возвращать неизменяемые копии или отделять изменяемое состояние от кэшированного свойства.
✍3
Python: задачки и вопросы
Развёрнутое пояснение:
1. State — перечисление, член State.OK имеет значение ok, но сам является отдельным объектом Enum.
2. Функция check сравнивает строку ok с объектом State.OK оператором равенства.
3. У Enum операция равенства считает равными только члены одного и того же перечисления, поэтому сравнение со строкой возвращает False.
4. В результате print выводит False.
Почему это важно: при рефакторинге строковых констант в Enum часто забывают, что сравнение со строкой из JSON или БД перестаёт работать. Правильно сравнивать через State(raw) == State.OK или raw == State.OK.value. Это типичная ошибка в валидации API и конфигурации.
2. Функция check сравнивает строку ok с объектом State.OK оператором равенства.
3. У Enum операция равенства считает равными только члены одного и того же перечисления, поэтому сравнение со строкой возвращает False.
4. В результате print выводит False.
Почему это важно: при рефакторинге строковых констант в Enum часто забывают, что сравнение со строкой из JSON или БД перестаёт работать. Правильно сравнивать через State(raw) == State.OK или raw == State.OK.value. Это типичная ошибка в валидации API и конфигурации.
✍3
Python: задачки и вопросы
Развёрнутое пояснение:
1. Создаётся пустой список queue.
2. defaultdict инициализируется фабрикой lambda: queue, которая при каждом обращении по отсутствующему ключу возвращает ссылку на этот же список.
3. tasks['api'] вызывает фабрику, возвращает queue и добавляет в него строку retry.
4. tasks['queue'] снова вызывает фабрику и возвращает тот же список queue, который уже содержит retry.
5. Поэтому print выводит ['retry'].
Почему это важно: такая ошибка возникает, когда разработчик хочет инициализировать значение изменяемым объектом и вместо конструктора list передаёт lambda, замкнутую на заранее созданный объект. В планировщиках задач, группировке событий по категориям или кэшировании результатов по ключам это приводит к тому, что разные ключи делят одно состояние. Правильный способ — передать list или функцию, создающую новый объект при каждом вызове, например defaultdict(list).
2. defaultdict инициализируется фабрикой lambda: queue, которая при каждом обращении по отсутствующему ключу возвращает ссылку на этот же список.
3. tasks['api'] вызывает фабрику, возвращает queue и добавляет в него строку retry.
4. tasks['queue'] снова вызывает фабрику и возвращает тот же список queue, который уже содержит retry.
5. Поэтому print выводит ['retry'].
Почему это важно: такая ошибка возникает, когда разработчик хочет инициализировать значение изменяемым объектом и вместо конструктора list передаёт lambda, замкнутую на заранее созданный объект. В планировщиках задач, группировке событий по категориям или кэшировании результатов по ключам это приводит к тому, что разные ключи делят одно состояние. Правильный способ — передать list или функцию, создающую новый объект при каждом вызове, например defaultdict(list).
✍2
Python: задачки и вопросы
Развёрнутое пояснение:
1. Создаётся словарь tags с ключами api и db.
2. Запускается цикл for key in tags, который получает итератор ключей словаря.
3. Итератор запоминает ожидаемое количество элементов на момент начала обхода.
4. При первом же ключе api условие срабатывает и вызывается tags.pop(key), удаляя элемент из словаря.
5. Словарь изменил размер во время итерации, поэтому при следующей попытке получить следующий ключ интерпретатор обнаруживает рассогласование и возбуждает RuntimeError: dictionary changed size during iteration.
6. print(tags) не выполняется, потому что исключение прерывает выполнение.
Почему это важно: такая ошибка часто возникает при фильтрации или очистке словарей состояния, кэша или метрик. Правильный способ — собрать ключи для удаления в отдельный список и удалять после цикла, либо создавать новый словарь через dict comprehension. Это позволяет избежать неожиданного падения на проде при обработке логов, конфигов или счётчиков.
2. Запускается цикл for key in tags, который получает итератор ключей словаря.
3. Итератор запоминает ожидаемое количество элементов на момент начала обхода.
4. При первом же ключе api условие срабатывает и вызывается tags.pop(key), удаляя элемент из словаря.
5. Словарь изменил размер во время итерации, поэтому при следующей попытке получить следующий ключ интерпретатор обнаруживает рассогласование и возбуждает RuntimeError: dictionary changed size during iteration.
6. print(tags) не выполняется, потому что исключение прерывает выполнение.
Почему это важно: такая ошибка часто возникает при фильтрации или очистке словарей состояния, кэша или метрик. Правильный способ — собрать ключи для удаления в отдельный список и удалять после цикла, либо создавать новый словарь через dict comprehension. Это позволяет избежать неожиданного падения на проде при обработке логов, конфигов или счётчиков.
✍1
Python: задачки и вопросы
Развёрнутое пояснение:
1. Список logs содержит четыре кортежа: две записи api и две db, чередующиеся. 2. itertools.groupby не сортирует данные и не ищет все одинаковые ключи во всём списке: он формирует новую группу каждый раз, когда ключ очередного элемента отличается от ключа предыдущего. 3. Последовательность ключей в logs: api, db, api, db. Поэтому группы получаются такими: api с одной записью, db с одной записью, снова api с одной записью и снова db с одной записью. 4. В dict comprehension каждый ключ перезаписывается при повторном вхождении. Сначала 'api' получает список из одной ошибки, потом 'db' — один успех, затем 'api' зативается второй группой из одной успешной записи, и в конце 'db' перезаписывается группой с одной ошибкой. 5. В итоге groups['api'] — это список из одного кортежа [('api', 'ok')], а len от него равен 1.
Почему это важно: в аналитике логов и отчётах часто ожидают, что groupby сгруппирует все записи по ключу, как SQL GROUP BY, но в Python он работает только над отсортированными или уже упорядоченными данными. Если пропустить сортировку, группы дробятся, а при записи в словарь последняя группа затирает предыдущие с тем же ключом. Это приводит к тихой потере данных и неверным агрегатам.
Почему это важно: в аналитике логов и отчётах часто ожидают, что groupby сгруппирует все записи по ключу, как SQL GROUP BY, но в Python он работает только над отсортированными или уже упорядоченными данными. Если пропустить сортировку, группы дробятся, а при записи в словарь последняя группа затирает предыдущие с тем же ключом. Это приводит к тихой потере данных и неверным агрегатам.
✍2
Приглашаем Go- и Python-разработчиков, аналитиков и продакт-менеджеров на тревел-тех хакатон от Островка.
Вам предстоит решить одну из двух AI-задач в сфере тревел-теха и побороться за главный приз — 1 000 000 ₽.
Присоединиться к хакатону можно из любой точки мира. Участвуйте командой до пяти человек и выбирайте один из двух треков:
Скорее присоединяйтесь по ссылке!
Please open Telegram to view this post
VIEW IN TELEGRAM