Python: задачки и вопросы
7.51K subscribers
1.26K photos
1 video
1 file
115 links
Вопросы и задачки для подготовки к собеседованиям и прокачки навыков

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

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

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

Другие наши проекты: https://tprg.ru/media
Download Telegram
Что выведет код в Python 3?
Anonymous Quiz
51%
['a', 'b', 'c'], 2
10%
['a', 'b', 'c'], 3
25%
['b', 'c'], 2
14%
Error
2👍2
Методы 𝚔𝚎𝚢𝚜(), 𝚟𝚊𝚕𝚞𝚎𝚜(), 𝚒𝚝𝚎𝚖𝚜() возвращают не списки, а динамические представления (views) словаря, которые автоматически обновляются при изменениях в оригинальном словаре.

Разбор по шагам:
🔘𝚍 = {'a': 10, 'b': 20} создаёт словарь с двумя парами.
🔘𝚔𝚎𝚢𝚜 = 𝚍.𝚔𝚎𝚢𝚜() возвращает 𝚍𝚒𝚌𝚝_𝚔𝚎𝚢𝚜(['a', 'b']) — представление ключей, отражающее текущее состояние 𝚍.
🔘𝚍['c'] = 30 добавляет новую пару; представление 𝚔𝚎𝚢𝚜 мгновенно видит три ключа, поэтому 𝚕𝚒𝚜𝚝(𝚔𝚎𝚢𝚜) даёт ['a', 'b', 'c'].
🔘𝚍.𝚙𝚘𝚙('a') удаляет ключ 'a'; представление снова обновляется, и теперь 𝚕𝚎𝚗(𝚔𝚎𝚢𝚜) возвращает 2 (остались 'b' и 'c').

Views — это не копии, а «живые» ссылки на словарь, экономящие память и время. В отличие от Python 2 (где 𝚍𝚒𝚌𝚝.𝚔𝚎𝚢𝚜() возвращал список-копию), в Python 3 представления всегда динамичны. Если бы код использовал 𝚕𝚒𝚜𝚝(𝚍.𝚔𝚎𝚢𝚜()) в начале, то 𝚘𝚕𝚍_𝚔𝚎𝚢𝚜 = 𝚕𝚒𝚜𝚝(𝚍.𝚔𝚎𝚢𝚜()), добавление 'c' не повлияло бы на 𝚘𝚕𝚍_𝚔𝚎𝚢𝚜 — оно осталось бы ['a', 'b'].
Please open Telegram to view this post
VIEW IN TELEGRAM
1
По умолчанию сортировка разных типов в Python 3 невозможна, но параметр key позволяет задать нормализацию данных. Ключ — кортеж (isinstance(x, str), int(x)): сначала сортируем по флагу «x — строка?» (False < True, значит числа идут раньше строк), затем по числовому значению int(x).

Разбор по шагам:
🔘Для 1 ключ (False, 1), для 2 — (False, 2). Для '3' — (True, 3), для '10' — (True, 10), для '20' — (True, 20).
🔘Сначала все элементы с False: 1, 2; затем True: '3', '10', '20'. Внутри групп сравнение по второму элементу ключа, то есть по числу после приведения.
🔘Поэтому результат — [1, 2, '3', '10', '20'].

Подводные камни:
🔘Без key будет TypeError, потому что числа и строки несравнимы.
🔘Если в данных встретится строка, не приводимая к int (например, 'x'), key упадёт с ValueError — для устойчивости можно использовать try/except в ключе или заранее фильтровать данные.

Вариант устойчивого ключа:

𝚍𝚎𝚏 𝚔(𝚡):
𝚝𝚛𝚢:
𝚛𝚎𝚝𝚞𝚛𝚗 (𝚒𝚜𝚒𝚗𝚜𝚝𝚊𝚗𝚌𝚎(𝚡, 𝚜𝚝𝚛), 𝚒𝚗𝚝(𝚡))
𝚎𝚡𝚌𝚎𝚙𝚝 𝚅𝚊𝚕𝚞𝚎𝙴𝚛𝚛𝚘𝚛:
𝚛𝚎𝚝𝚞𝚛𝚗 (𝚒𝚜𝚒𝚗𝚜𝚝𝚊𝚗𝚌𝚎(𝚡, 𝚜𝚝𝚛), 𝚏𝚕𝚘𝚊𝚝('𝚒𝚗𝚏'))
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2
Генератор 𝚐𝚎𝚗 создаётся как выражение: 𝚐𝚎𝚗 = ( 𝚡 * 𝚡 𝚏𝚘𝚛 𝚡 𝚒𝚗 𝚖𝚊𝚔𝚎() 𝚒𝚏 𝚡 % 𝟸 ). В этот момент 𝚖𝚊𝚔𝚎() УЖЕ вызывается — Python сразу вычисляет самый внешний итерируемый объект, чтобы создать итератор. Поэтому «build» выводится при создании генератора, ДО строки с 𝚙𝚛𝚒𝚗𝚝. Ленивыми остаются только фильтр 𝚒𝚏 𝚡 % 𝟸 и преобразование 𝚡 * 𝚡 — они применяются при итерации.

В строке 𝚙𝚛𝚒𝚗𝚝(𝚜𝚞𝚖(𝚐𝚎𝚗), 𝚕𝚒𝚜𝚝(𝚐𝚎𝚗)) аргументы оцениваются слева направо.

🔘Сначала вызывается 𝚜𝚞𝚖(𝚐𝚎𝚗). Генератор начинает итерацию по списку из 𝚖𝚊𝚔𝚎(), применяя фильтр 𝚒𝚏 𝚡 % 𝟸 — остаются 𝟷 и 𝟹. К ним применяется 𝚡 * 𝚡 → 𝟷, 𝟿, а 𝚜𝚞𝚖 даёт 𝟷𝟶.

🔘Затем вызывается 𝚕𝚒𝚜𝚝(𝚐𝚎𝚗). Но генератор уже исчерпан предыдущей суммой: его внутренний итератор достиг конца. Повторная попытка даёт пустую последовательность → []. При этом list обрабатывает StopIteration и ошибки не будет.

Итоговая печать выводит «𝟷𝟶 []». Поэтому верный вариант — «build» (вывелось ДО строки с 𝚙𝚛𝚒𝚗𝚝), а затем «𝟷𝟶 []».

Полезные выводы:
🔘 Генераторы «одноразовые»: один проход — и состояние на конце. Хотите повторного обхода — сохраните данные: 𝚍𝚊𝚝𝚊 = 𝚕𝚒𝚜𝚝(𝚐𝚎𝚗) или создайте новый генератор.
🔘Самый внешний итератор (𝚖𝚊𝚔𝚎()) вычисляется немедленно при создании генератора, поэтому побочные эффекты в нём проявятся сразу. Ленивыми остаются только условия и преобразования эллементов.
Please open Telegram to view this post
VIEW IN TELEGRAM