По шагам:
1️⃣В начале вызывается функция 𝚏𝚘𝚘, внутри создаётся список 𝚗𝚞𝚖𝚜 = [𝟷, 𝟸, 𝟹].
2️⃣В блоке 𝚝𝚛𝚢 запускается цикл 𝚏𝚘𝚛 𝚒 𝚒𝚗 𝚛𝚊𝚗𝚐𝚎(𝚕𝚎𝚗(𝚗𝚞𝚖𝚜)), переменная 𝚒 по очереди принимает значения 𝟶, 𝟷, 𝟸.
3️⃣При 𝚒 = 𝟶 условие 𝚒 == 𝟷 ложно, выполняется умножение 𝚗𝚞𝚖𝚜[𝟶] = 𝚗𝚞𝚖𝚜[𝟶] * 𝟷𝟶, и список становится [𝟷𝟶, 𝟸, 𝟹].
4️⃣При 𝚒 = 𝟷 условие 𝚒 == 𝟷 истинно, выполняется 𝚛𝚊𝚒𝚜𝚎 𝚅𝚊𝚕𝚞𝚎𝙴𝚛𝚛𝚘𝚛(𝚍𝚊𝚝𝚊), до строки с умножением элемента список уже не доходит, поэтому элементы с индексами 𝟷 и 𝟸 остаются как были: [𝟷𝟶, 𝟸, 𝟹].
5️⃣Исключение перехватывается в блоке 𝚎𝚡𝚌𝚎𝚙𝚝 𝚅𝚊𝚕𝚞𝚎𝙴𝚛𝚛𝚘𝚛, там подготавливается к возврату кортеж ("error", 𝚗𝚞𝚖𝚜), но фактический выход из функции откладывается до завершения блока 𝚏𝚒𝚗𝚊𝚕𝚕𝚢.
6️⃣В блоке 𝚏𝚒𝚗𝚊𝚕𝚕𝚢 в тот же объект списка 𝚗𝚞𝚖𝚜 добавляется элемент 𝟿𝟿 через вызов 𝚗𝚞𝚖𝚜.𝚊𝚙𝚙𝚎𝚗𝚍(𝟿𝟿), и список становится [𝟷𝟶, 𝟸, 𝟹, 𝟿𝟿].
7️⃣Затем вызывается 𝚙𝚛𝚒𝚗𝚝(𝚗𝚞𝚖𝚜), в стандартный вывод уходит единственная строка с представлением списка [𝟷𝟶, 𝟸, 𝟹, 𝟿𝟿], а возвращаемое значение функции 𝚏𝚘𝚘 нигде не используется.
Из этой задачи видно, что блок 𝚏𝚒𝚗𝚊𝚕𝚕𝚢 всегда выполняется при выходе из 𝚝𝚛𝚢/𝚎𝚡𝚌𝚎𝚙𝚝, даже если уже выбран результат 𝚛𝚎𝚝𝚞𝚛𝚗 или поймано исключение, и может ещё изменить состояние объектов. Мы также чётко видим, что работа с изменяемыми структурами данных внутри 𝚏𝚒𝚗𝚊𝚕𝚕𝚢 напрямую влияет на то, что попадёт в вывод или вернётся из функции, поэтому такие побочные эффекты лучше держать под контролем и не недооценивать их.
Post #4509
872
- ❤ 2
- 👍 2