From d0dd3ad2b7f5ccf73aeb9aba2d2f570f5cfff218 Mon Sep 17 00:00:00 2001 From: Vadim Nifadev <36514612+nifadyev@users.noreply.github.com> Date: Sat, 27 Apr 2024 12:21:12 +0300 Subject: [PATCH] Fix typos and spelling --- translations/README-ru.md | 392 ++++++++++++++++++++++---------------- 1 file changed, 226 insertions(+), 166 deletions(-) diff --git a/translations/README-ru.md b/translations/README-ru.md index 2f30ae0..9cde024 100644 --- a/translations/README-ru.md +++ b/translations/README-ru.md @@ -1,98 +1,163 @@

What the f*ck Python! 😱

-

Изучение и понимание Python с помощью нестандартного поведения и "магического" поведения.

+

Изучение и понимание Python с помощью удивительных примеров поведения.

-Переводы: [English Original](https://github.com/satwikkansal/wtfpython) [Chinese 中文](https://github.com/robertparley/wtfpython-cn) | [Vietnamese Tiếng Việt](https://github.com/vuduclyunitn/wtfptyhon-vi) | [Spanish Español](https://web.archive.org/web/20220511161045/https://github.com/JoseDeFreitas/wtfpython-es) | [Korean 한국어](https://github.com/buttercrab/wtfpython-ko) | [Russian Русский](https://github.com/nifadyev/wtfpython/tree/main/translations/README-ru.md) | [German Deutsch](https://github.com/BenSt099/wtfpython) | [Add translation](https://github.com/satwikkansal/wtfpython/issues/new?title=Add%20translation%20for%20[LANGUAGE]&body=Expected%20time%20to%20finish:%20[X]%20weeks.%20I%27ll%20start%20working%20on%20it%20from%20[Y].) +Переводы: [English Original](https://github.com/satwikkansal/wtfpython) [Chinese 中文](https://github.com/robertparley/wtfpython-cn) | [Vietnamese Tiếng Việt](https://github.com/vuduclyunitn/wtfptyhon-vi) | [Spanish Español](https://web.archive.org/web/20220511161045/https://github.com/JoseDeFreitas/wtfpython-es) | [Korean 한국어](https://github.com/buttercrab/wtfpython-ko) | [Russian Русский](https://github.com/satwikkansal/wtfpython/tree/main/translations/README-ru.md) | [German Deutsch](https://github.com/BenSt099/wtfpython) | [Add translation](https://github.com/satwikkansal/wtfpython/issues/new?title=Add%20translation%20for%20[LANGUAGE]&body=Expected%20time%20to%20finish:%20[X]%20weeks.%20I%27ll%20start%20working%20on%20it%20from%20[Y].) Альтернативные способы: [Интерактивный сайт](https://wtfpython-interactive.vercel.app) | [Интерактивный Jupiter notebook](https://colab.research.google.com/github/satwikkansal/wtfpython/blob/master/irrelevant/wtf.ipynb) | [CLI](https://pypi.python.org/pypi/wtfpython) -Python, будучи прекрасно спроектированным высокоуровневым языком программирования, предоставляет множество возможностей для удобства программиста. Но иногда результаты работы Python кода могут показаться неочевидными на первый взгляд. +Python, будучи прекрасно спроектированным высокоуровневым языком программирования, предоставляет множество возможностей для удобства программиста. Но иногда поведение Python кода могут показаться запутывающим на первый взгляд. -**wtfpython** задуман как проект, пытающийся объяснить, что именно происходит под капотом некоторых неочевидных фрагментов кода и менее известных возможностей Python. +**wtfpython** задуман как проект, пытающийся объяснить, что именно происходит под капотом неочевидных фрагментов кода и малоизвестных возможностей Python. -Если вы опытный программист на Python, вы можете принять это как вызов и правильно объяснить WTF ситуации с первой попытки. Возможно, вы уже сталкивались с некоторыми из них раньше, и я смогу оживить ваши старые добрые воспоминания! 😅 +Если вы опытный питонист, вы можете принять это как вызов и правильно объяснить WTF ситуации с первой попытки. Возможно, вы уже сталкивались с некоторыми из них раньше, и я смогу оживить ваши старые добрые воспоминания! 😅 PS: Если вы уже читали **wtfpython** раньше, с изменениями можно ознакомиться [здесь](https://github.com/satwikkansal/wtfpython/releases/) (примеры, отмеченные звездочкой - это примеры, добавленные в последней основной редакции). Ну что ж, приступим... # Содержание -* [Содержание](#Содержание) -* [Структура примера](#Структура-примера) -* [Применение](#Применение) -* [👀 Примеры](#👀-Примеры) - * [Секция: Напряги мозги!](#Секция:-Напряги-мозги!) - * [▶ Первым делом!](#▶-Первым-делом!) - * [▶ Строки иногда ведут себя непредсказуемо](#▶-Строки-иногда-ведут-себя-непредсказуемо) - * [▶ Осторожнее с цепочкой операций](#▶-Осторожнее-с-цепочкой-операций) - * [▶ Как не надо использовать оператор `is`](#▶-Как-не-надо-использовать-оператор-`is`) - * [▶ Мистическое хэширование](#▶-Мистическое-хэширование) - * [▶ В глубине души мы все одинаковы.](#▶-В-глубине-души-мы-все-одинаковы.) - * [▶ Беспорядок внутри порядка *](#▶-Беспорядок-внутри-порядка--*) - * [▶ Продолжай пытаться... *](#▶-Продолжай-пытаться...-*) - * [▶ Для чего?](#▶-Для-чего?) - * [▶ Расхождение во времени исполнения](#▶-Расхождение-во-времени-исполнения) - * [▶ `is not ...` не является `is (not ...)`](#▶-`is-not-...`-не-является-`is-(not-...)`) - * [▶ Крестики-нолики, где X побеждает с первой попытки!](#▶-Крестики-нолики,-где-X-побеждает-с-первой-попытки!) - * [▶ Переменная Шредингера *](#▶-Переменная-Шредингера-*) - * [▶ Проблема курицы и яйца *](#▶-Проблема-курицы-и-яйца-*) - * [▶ Отношения между подклассами](#▶-Отношения-между-подклассами) - * [▶ Равенство и тождество методов](#▶-Равенство-и-тождество-методов) - * [▶ All-true-ation (непереводимая игра слов) *](#▶-All-true-ation-(непереводимая-игра-слов)-*) - * [▶ Неожиданная запятая](#▶-Неожиданная-запятая) - * [▶ Строки и обратные слэши](#▶-Строки-и-обратные-слэши) - * [▶ Не узел! (eng. not knot!)](#▶-Не-узел!-(eng.-not-knot!)) - * [▶ Строки наполовину в тройных кавычках](#▶-Строки-наполовину-в-тройных-кавычках) - * [▶ Что не так с логическими значениями?](#▶-Что-не-так-с-логическими-значениями?) - * [▶ Атрибуты класса и экземпляра](#▶-Атрибуты-класса-и-экземпляра) - * [▶ Возврат None из генератора](#▶-Возврат-None-из-генератора) - * [▶ Yield from возвращает... *](#▶-Yield-from-возвращает...-*) - * [▶ Nan-рефлексивность *](#▶-Nan-рефлексивность-*) - * [▶ Мутируем немутируемое!](#▶-Мутируем-немутируемое!) - * [▶ Исчезающая переменная из внешней области видимости](#▶-Исчезающая-переменная-из-внешней-области-видимости) - * [▶ Превышение предела целочисленного преобразования строк](#▶-Превышение-предела-целочисленного-преобразования-строк) - * [Секция: Скользкие склоны](#Секция:-Скользкие-склоны) - * [▶ Изменение словаря во время прохода по нему](#▶-Изменение-словаря-во-время-прохода-по-нему) - * [▶ Упрямая операция `del`](#▶-Упрямая-операция-`del`) - * [▶ Переменная за пределами видимости](#▶-Переменная-за-пределами-видимости) - * [▶ Удаление элемента списка во время прохода по списку](#▶-Удаление-элемента-списка-во-время-прохода-по-списку) - * [▶ Сжатие итераторов с потерями *](#▶-Сжатие-итераторов-с-потерями-*) - * [▶ Утечка переменных внутри цикла](#▶-Утечка-переменных-внутри-цикла) - * [▶ Остерегайтесь изменяемых аргументов по умолчанию!](#▶-Остерегайтесь-изменяемых-аргументов-по-умолчанию!) - * [▶ Ловля исключений](#▶-Ловля-исключений) - * [▶ Одни и те же операнды, разная история!](#▶-Одни-и-те-же-операнды,-разная-история!) - * [▶ Разрешение имен игнорирует область видимости класса](#▶-Разрешение-имен-игнорирует-область-видимости-класса) - * [▶ Округляясь как банкир *](#▶-Округляясь-как-банкир-*) - * [▶ Иголки в стоге сена *](#▶-Иголки-в-стоге-сена-*) - * [▶ Сплиты (splitsies) *](#▶-Сплиты-(splitsies)-*) - * [▶ Подстановочное импортирование (wild imports) *](#▶-Подстановочное-импортирование-(wild-imports)-*) - * [▶ Все ли отсортировано? *](#▶-Все-ли-отсортировано?-*) - * [▶ Полночи не существует?](#▶-Полночи-не-существует?) - * [Секция: Скрытые сокровища!](#Секция:-Скрытые-сокровища!) - * [▶ Python, можешь ли ты помочь взлелеть?](#▶-Python,-можешь-ли-ты-помочь-взлелеть?) - * [▶ `goto`, но почему?](#▶-`goto`,-но-почему?) - * [▶ Держитесь!](#▶-Держитесь!) - * [▶ Давайте познакомимся с дружелюбным Дядей Барри](#▶-Давайте-познакомимся-с-дружелюбным-Дядей-Барри) - * [▶ Даже Python понимает, что любовь - это сложно.](#▶-Даже-Python-понимает,-что-любовь---это-сложно.) - * [▶ Да, оно существует!](#▶-Да,-оно-существует!) - * [▶ Многоточие *](#▶-Многоточие-*) - * [▶ Писконечность (Inpinity)](#▶-Писконечность-(Inpinity)) - * [▶ Давайте искажать](#▶-Давайте-искажать) - * [Секция: Внешность обманчива!](#Секция:-Внешность-обманчива!) - * [▶ Пропускаем строки?](#▶-Пропускаем-строки?) - * [▶ Телепортация](#▶-Телепортация) - * [▶ Что-то не так...](#▶-Что-то-не-так...) - * [Секция: Разное](#Секция:-Разное) - * [▶ `+=` быстрее](#▶-`+=`-быстрее) - * [▶ Сделаем гигантскую строку!](#▶-Сделаем-гигантскую-строку!) - * [▶ Замедляем поиск по `dict` *](#▶-Замедляем-поиск-по-`dict`-*) - * [▶ Раздуваем экземпляры словарей *](#▶-Раздуваем-экземпляры-словарей-*) - * [▶ Минорное *](#▶-Минорное-*) -* [Вклад в проект](#Вклад-в-проект) -* [Благодарности](#Благодарности) -* [🎓 Лицензия](#🎓-Лицензия) - * [Удиви своих друзей!](#Удиви-своих-друзей!) - * [Нужна PDF версия?](#Нужна-PDF-версия?) +- [Содержание](#содержание) +- [Структура примера](#структура-примера) +- [Применение](#применение) +- [👀 Примеры](#-примеры) + - [Секция: Напряги мозги!](#секция-напряги-мозги) + - [▶ Первым делом!](#-первым-делом) + - [💡 Обьяснение](#-обьяснение) + - [▶ Строки иногда ведут себя непредсказуемо](#-строки-иногда-ведут-себя-непредсказуемо) + - [💡 Объяснение](#-объяснение) + - [▶ Осторожнее с цепочкой операций](#-осторожнее-с-цепочкой-операций) + - [💡 Объяснение:](#-объяснение-1) + - [▶ Как не надо использовать оператор `is`](#-как-не-надо-использовать-оператор-is) + - [💡 Объяснение:](#-объяснение-2) + - [▶ Мистическое хеширование](#-мистическое-хеширование) + - [💡 Объяснение](#-объяснение-3) + - [▶ В глубине души мы все одинаковы.](#-в-глубине-души-мы-все-одинаковы) + - [💡 Объяснение:](#-объяснение-4) + - [▶ Беспорядок внутри порядка \*](#-беспорядок-внутри-порядка-) + - [💡 Объяснение:](#-объяснение-5) + - [▶ Продолжай пытаться... \*](#-продолжай-пытаться-) + - [💡 Объяснение:](#-объяснение-6) + - [▶ Для чего?](#-для-чего) + - [💡 Объяснение:](#-объяснение-7) + - [▶ Расхождение во времени исполнения](#-расхождение-во-времени-исполнения) + - [💡 Объяснение](#-объяснение-8) + - [▶ `is not ...` не является `is (not ...)`](#-is-not--не-является-is-not-) + - [💡 Объяснение](#-объяснение-9) + - [▶ Крестики-нолики, где X побеждает с первой попытки!](#-крестики-нолики-где-x-побеждает-с-первой-попытки) + - [💡 Объяснение:](#-объяснение-10) + - [▶ Переменная Шредингера \*](#-переменная-шредингера-) + - [💡 Объяснение:](#-объяснение-11) + - [▶ Проблема курицы и яйца \*](#-проблема-курицы-и-яйца-) + - [💡 Объяснение](#-объяснение-12) + - [▶ Отношения между подклассами](#-отношения-между-подклассами) + - [💡 Объяснение](#-объяснение-13) + - [▶ Равенство и тождество методов](#-равенство-и-тождество-методов) + - [💡 Объяснение](#-объяснение-14) + - [▶ All-true-ation (непереводимая игра слов) \*](#-all-true-ation-непереводимая-игра-слов-) + - [💡 Объяснение:](#-объяснение-15) + - [💡 Объяснение:](#-объяснение-16) + - [▶ Строки и обратные слэши](#-строки-и-обратные-слэши) + - [💡 Объяснение](#-объяснение-17) + - [▶ Не узел! (англ. not knot!)](#-не-узел-англ-not-knot) + - [💡 Объяснение](#-объяснение-18) + - [▶ Строки, наполовину обернутые в тройные кавычки](#-строки-наполовину-обернутые-в-тройные-кавычки) + - [💡 Объяснение:](#-объяснение-19) + - [▶ Что не так с логическими значениями?](#-что-не-так-с-логическими-значениями) + - [💡 Объяснение:](#-объяснение-20) + - [▶ Атрибуты класса и экземпляра](#-атрибуты-класса-и-экземпляра) + - [💡 Объяснение:](#-объяснение-21) + - [▶ Возврат None из генератора](#-возврат-none-из-генератора) + - [💡 Объяснение:](#-объяснение-22) + - [▶ Yield from возвращает... \*](#-yield-from-возвращает-) + - [💡 Объяснение:](#-объяснение-23) + - [▶ Nan-рефлексивность \*](#-nan-рефлексивность-) + - [💡 Объяснение:](#-объяснение-24) + - [▶ Изменяем неизменяемое!](#-изменяем-неизменяемое) + - [💡 Объяснение:](#-объяснение-25) + - [▶ Исчезающая переменная из внешней области видимости](#-исчезающая-переменная-из-внешней-области-видимости) + - [💡 Объяснение:](#-объяснение-26) + - [▶ Загадочное преобразование типов ключей](#-загадочное-преобразование-типов-ключей) + - [💡 Объяснение:](#-объяснение-27) + - [▶ Посмотрим, сможете ли вы угадать что здесь?](#-посмотрим-сможете-ли-вы-угадать-что-здесь) + - [💡 Объяснение:](#-объяснение-28) + - [▶ Превышение предела целочисленного преобразования строк](#-превышение-предела-целочисленного-преобразования-строк) + - [💡 Объяснение:](#-объяснение-29) + - [Секция: Скользкие склоны](#секция-скользкие-склоны) + - [▶ Изменение словаря во время прохода по нему](#-изменение-словаря-во-время-прохода-по-нему) + - [💡 Объяснение:](#-объяснение-30) + - [▶ Упрямая операция `del`](#-упрямая-операция-del) + - [💡 Объяснение:](#-объяснение-31) + - [▶ Переменная за пределами видимости](#-переменная-за-пределами-видимости) + - [💡 Объяснение:](#-объяснение-32) + - [▶ Удаление элемента списка во время прохода по списку](#-удаление-элемента-списка-во-время-прохода-по-списку) + - [💡 Объяснение:](#-объяснение-33) + - [▶ Сжатие итераторов с потерями \*](#-сжатие-итераторов-с-потерями-) + - [💡 Объяснение:](#-объяснение-34) + - [▶ Утечка переменных внутри цикла](#-утечка-переменных-внутри-цикла) + - [💡 Объяснение:](#-объяснение-35) + - [▶ Остерегайтесь изменяемых аргументов по умолчанию!](#-остерегайтесь-изменяемых-аргументов-по-умолчанию) + - [💡 Объяснение:](#-объяснение-36) + - [▶ Ловля исключений](#-ловля-исключений) + - [💡 Объяснение](#-объяснение-37) + - [▶ Одни и те же операнды, разная история!](#-одни-и-те-же-операнды-разная-история) + - [💡 Объяснение:](#-объяснение-38) + - [▶ Разрешение имен игнорирует область видимости класса](#-разрешение-имен-игнорирует-область-видимости-класса) + - [💡 Объяснение](#-объяснение-39) + - [▶ Округляясь как банкир \*](#-округляясь-как-банкир-) + - [💡 Объяснение:](#-объяснение-40) + - [▶ Иголки в стоге сена \*](#-иголки-в-стоге-сена-) + - [💡 Объяснение:](#-объяснение-41) + - [▶ Сплиты (splitsies) \*](#-сплиты-splitsies-) + - [💡 Объяснение](#-объяснение-42) + - [▶ Подстановочное импортирование (wild imports) \*](#-подстановочное-импортирование-wild-imports-) + - [💡 Объяснение:](#-объяснение-43) + - [▶ Все ли отсортировано? \*](#-все-ли-отсортировано-) + - [💡 Объяснение:](#-объяснение-44) + - [▶ Полночи не существует?](#-полночи-не-существует) + - [💡 Объяснение:](#-объяснение-45) + - [Секция: Скрытые сокровища!](#секция-скрытые-сокровища) + - [▶ Python, можешь ли ты помочь взлететь?](#-python-можешь-ли-ты-помочь-взлететь) + - [💡 Объяснение:](#-объяснение-46) + - [▶ `goto`, но почему?](#-goto-но-почему) + - [💡 Объяснение:](#-объяснение-47) + - [▶ Держитесь!](#-держитесь) + - [💡 Объяснение:](#-объяснение-48) + - [▶ Давайте познакомимся с дружелюбным Дядей Барри](#-давайте-познакомимся-с-дружелюбным-дядей-барри) + - [💡 Объяснение:](#-объяснение-49) + - [▶ Даже Python понимает, что любовь - это сложно.](#-даже-python-понимает-что-любовь---это-сложно) + - [💡 Объяснение:](#-объяснение-50) + - [▶ Да, оно существует!](#-да-оно-существует) + - [💡 Объяснение:](#-объяснение-51) + - [▶ Многоточие \*](#-многоточие-) + - [💡 Объяснение](#-объяснение-52) + - [▶ Писконечность (Inpinity)](#-писконечность-inpinity) + - [💡 Объяснение:](#-объяснение-53) + - [▶ Давайте искажать](#-давайте-искажать) + - [💡 Объяснение:](#-объяснение-54) + - [Секция: Внешность обманчива!](#секция-внешность-обманчива) + - [▶ Пропускаем строки?](#-пропускаем-строки) + - [💡 Объяснение](#-объяснение-55) + - [▶ Телепортация](#-телепортация) + - [💡 Объяснение:](#-объяснение-56) + - [▶ Что-то не так...](#-что-то-не-так) + - [💡 Объяснение](#-объяснение-57) + - [Секция: Разное](#секция-разное) + - [▶ `+=` быстрее `+`](#--быстрее-) + - [💡 Объяснение:](#-объяснение-58) + - [▶ Сделаем гигантскую строку!](#-сделаем-гигантскую-строку) + - [💡 Объяснение](#-объяснение-59) + - [▶ Замедляем поиск по `dict` \*](#-замедляем-поиск-по-dict-) + - [💡 Объяснение:](#-объяснение-60) + - [▶ Раздуваем экземпляры словарей \*](#-раздуваем-экземпляры-словарей-) + - [💡 Объяснение:](#-объяснение-61) + - [▶ Минорное \*](#-минорное-) +- [Вклад в проект](#вклад-в-проект) +- [Благодарности](#благодарности) + - [Несколько хороших ссылок!](#несколько-хороших-ссылок) +- [🎓 Лицензия](#-лицензия) + - [Удиви своих друзей!](#удиви-своих-друзей) + - [Нужна PDF версия?](#нужна-pdf-версия) # Структура примера @@ -137,11 +202,11 @@ PS: Если вы уже читали **wtfpython** раньше, с измен Хороший способ получить максимальную пользу от этих примеров - читать их последовательно, причем для каждого из них важно: -- Внимательно изучить исходный код. Если вы опытный программист на Python, то в большинстве случаев сможете предугадать, что произойдет дальше. +- Внимательно изучить исходный код. Если вы опытный Python программист, то в большинстве случаев сможете предугадать, что произойдет дальше. - Прочитать фрагменты вывода и, - Проверить, совпадают ли выходные данные с вашими ожиданиями. - Убедиться, что вы знаете точную причину, по которой вывод получился именно таким. - - Если ответ отрицательный (что совершенно нормально), сделать глубокий вдох и прочитать объяснение (а если пример все еще непонятен, и создайте issue [здесь](https://github.com/satwikkansal/wtfpython/issues/new)). + - Если ответ отрицательный (что совершенно нормально), сделать глубокий вдох и прочитать объяснение (а если пример все еще непонятен, и создайте [issue](https://github.com/satwikkansal/wtfpython/issues/new)). - Если "да", ощутите мощь своих познаний в Python и переходите к следующему примеру. PS: Вы также можете читать WTFPython в командной строке, используя [pypi package](https://pypi.python.org/pypi/wtfpython), @@ -344,7 +409,7 @@ False - Строки интернируются во время компиляции (`'wtf'` будет интернирована, но `''.join(['w'', 't', 'f'])` - нет) - Строки, не состоящие из букв ASCII, цифр или знаков подчеркивания, не интернируются. В примере выше `'wtf!'` не интернируется из-за `!`. Реализацию этого правила в CPython можно найти [здесь](https://github.com/python/cpython/blob/3.6/Objects/codeobject.c#L19) ![image](/images/string-intern/string_intern.png) -- Когда переменные `a` и `b` принимают значение `"wtf!"` в одной строке, интерпретатор Python создает новый объект, а затем одновременно ссылается на вторую переменную. Если это выполняется в отдельных строках, он не "знает", что уже существует `"wtf!"` как объект (потому что `"wtf!"` не является неявно интернированным в соответствии с фактами, упомянутыми выше). Это оптимизация во время компиляции, не применяется к версиям CPython 3.7.x (более подробное обсуждение смотрите здесь [issue](https://github.com/satwikkansal/wtfpython/issues/100)). +- Когда переменные `a` и `b` принимают значение `"wtf!"` в одной строке, интерпретатор Python создает новый объект, а затем одновременно ссылается на вторую переменную. Если это выполняется в отдельных строках, он не "знает", что уже существует `"wtf!"` как объект (потому что `"wtf!"` не является неявно интернированным в соответствии с фактами, упомянутыми выше). Это оптимизация во время компиляции, не применяется к версиям CPython 3.7.x (более подробное обсуждение смотрите [здесь](https://github.com/satwikkansal/wtfpython/issues/100)). - Единица компиляции в интерактивной среде IPython состоит из одного оператора, тогда как в случае модулей она состоит из всего модуля. `a, b = "wtf!", "wtf!"` - это одно утверждение, тогда как `a = "wtf!"; b = "wtf!"` - это два утверждения в одной строке. Это объясняет, почему тождества различны в `a = "wtf!"; b = "wtf!"`, но одинаковы при вызове в модуле. - Резкое изменение в выводе четвертого фрагмента связано с [peephole optimization](https://en.wikipedia.org/wiki/Peephole_optimization) техникой, известной как складывание констант (англ. Constant folding). Это означает, что выражение `'a'*20` заменяется на `'aaaaaaaaaaaaaaaaaaaa'` во время компиляции, чтобы сэкономить несколько тактов во время выполнения. Складывание констант происходит только для строк длиной менее 21. (Почему? Представьте себе размер файла `.pyc`, созданного в результате выполнения выражения `'a'*10**10`). [Вот](https://github.com/python/cpython/blob/3.6/Python/peephole.c#L288) исходный текст реализации для этого. - Примечание: В Python 3.7 складывание констант было перенесено из оптимизатора peephole в новый оптимизатор AST с некоторыми изменениями в логике, поэтому четвертый фрагмент не работает в Python 3.7. Подробнее об изменении можно прочитать [здесь](https://bugs.python.org/issue11549). @@ -378,7 +443,7 @@ False #### 💡 Объяснение: -Согласно https://docs.python.org/3/reference/expressions.html#comparisons +Согласно [документации](https://docs.python.org/3/reference/expressions.html#comparisons) > Формально, если a, b, c, ..., y, z - выражения, а op1, op2, ..., opN - операторы сравнения, то a op1 b op2 c ... y opN z эквивалентно a op1 b и b op2 c и ... y opN z, за исключением того, что каждое выражение оценивается не более одного раза. @@ -491,7 +556,7 @@ False Подобная оптимизация применима и к другим **изменяемым** объектам, таким как пустые кортежи. Поскольку списки являются изменяемыми, поэтому `[] is []` вернет `False`, а `() is ()` вернет `True`. Это объясняет наш второй фрагмент. Перейдем к третьему, -**И `a`, и `b` ссылаются на один и тот же объект при инициализации одним и тем же значением в одной и той же строкеi**. +**И `a`, и `b` ссылаются на один и тот же объект при инициализации одним и тем же значением в одной и той же строке**. **Вывод** @@ -511,7 +576,7 @@ False * Когда a и b инициализируются со значением `257` в одной строке, интерпретатор Python создает новый объект, а затем одновременно ссылается на него во второй переменной. Если делать это в отдельных строках, интерпретатор не "знает", что объект `257` уже существует. -* Это оптимизация компилятора и относится именно к интерактивной среде. Когда вы вводите две строки в интерпретаторе, они компилируются отдельно, поэтому оптимизируются отдельно. Если выполнить этот пример в файле `.py', поведение будет отличаться, потому что файл компилируется весь сразу. Эта оптимизация не ограничивается целыми числами, она работает и для других неизменяемых типов данных, таких как строки (проверьте пример "Строки - это сложно") и плавающие числа, +* Эта оптимизация компилятора относится именно к интерактивной среде. Когда вы вводите две строки в интерпретаторе, они компилируются отдельно, поэтому оптимизируются отдельно. Если выполнить этот пример в файле `.py', поведение будет отличаться, потому что файл компилируется целиком. Эта оптимизация не ограничивается целыми числами, она работает и для других неизменяемых типов данных, таких как строки (смотреть пример "Строки - это сложно") и плавающие числа, ```py >>> a, b = 257.0, 257.0 @@ -519,12 +584,12 @@ False True ``` -* Почему это не сработало в Python 3.7? Абстрактная причина в том, что такие оптимизации компилятора зависят от реализации (т.е. могут меняться в зависимости от версии, ОС и т.д.). Я все еще выясняю, какое именно изменение реализации вызвало проблему, вы можете проверить этот [issue](https://github.com/satwikkansal/wtfpython/issues/100) для получения обновлений. +* Почему это не сработало в Python 3.7? Абстрактная причина в том, что такие оптимизации компилятора зависят от реализации (т.е. могут меняться в зависимости от версии, ОС и т.д.). Я все еще выясняю, какое именно изменение реализации вызвало проблему, вы можете следить за этим [issue](https://github.com/satwikkansal/wtfpython/issues/100) для получения обновлений. --- -### ▶ Мистическое хэширование +### ▶ Мистическое хеширование 1\. ```py @@ -556,7 +621,7 @@ complex #### 💡 Объяснение -* Уникальность ключей в словаре Python определяется *эквивалентностью*, а не тождеством. Поэтому, даже если `5`, `5.0` и `5 + 0j` являются различными объектами разных типов, поскольку они равны, они не могут находиться в одном и том же `dict` (или `set`). Как только вы вставите любой из них, попытка поиска по любому другому, но эквивалентному ключу будет успешной с исходным сопоставленным значением (а не завершится ошибкой `KeyError`): +* Уникальность ключей в словаре Python определяется *эквивалентностью*, а не тождеством. Поэтому, даже если `5`, `5.0` и `5 + 0j` являются различными объектами разных типов, поскольку они эквивалентны, они не могут находиться в одном и том же `dict` (или `set`). Как только вы вставите любой из них, попытка поиска по любому другому, но эквивалентному ключу будет успешной с исходным сопоставленным значением (а не завершится ошибкой `KeyError`): ```py >>> 5 == 5.0 == 5 + 0j True @@ -569,7 +634,7 @@ complex >>> (5 in some_dict) and (5 + 0j in some_dict) True ``` -* Это применимо и во время присваения значения элементу. Поэтому, в выражении `some_dict[5] = "Python"` Python находит существующий элемент с эквивалентным ключом `5.0 -> "Ruby"`, перезаписывает его значение на место, а исходный ключ оставляет в покое. +* Это применимо и во время присваивания значения элементу. Поэтому, в выражении `some_dict[5] = "Python"` Python находит существующий элемент с эквивалентным ключом `5.0 -> "Ruby"`, перезаписывает его значение на место, а исходный ключ оставляет в покое. ```py >>> some_dict {5.0: 'Ruby'} @@ -577,16 +642,17 @@ complex >>> some_dict {5.0: 'Python'} ``` -* Итак, как мы можем обновить ключ до `5` (вместо `5.0`)? На самом деле мы не можем сделать это обновление на месте, но что мы можем сделать, так это сначала удалить ключ (`del some_dict[5.0]`), а затем установить его (`some_dict[5]`), чтобы получить целое число `5` в качестве ключа вместо плавающего `5.0`, хотя это нужно в редких случаях. +* Итак, как мы можем обновить ключ до `5` (вместо `5.0`)? На самом деле мы не можем сделать это обновление на месте, но все же это возможно, нужно сначала удалить ключ (`del some_dict[5.0]`), а затем установить его (`some_dict[5]`), чтобы получить целое число `5` в качестве ключа вместо плавающего `5.0`, хотя это нужно в редких случаях. + +* Как Python нашел `5` в словаре, содержащем `5.0`? Python делает это за постоянное время без необходимости сканирования каждого элемента, используя хэш-функции. Когда Python ищет ключ `foo` в словаре, он сначала вычисляет `hash(foo)` (что выполняется в постоянном времени). Поскольку в Python требуется, чтобы объекты, которые одинаковы в сравнении, имели одинаковое хэш-значение (смотри [документацию](https://docs.python.org/3/reference/datamodel.html#object.__hash__)), `5`, `5.0` и `5 + 0j` выполняют это условие. -* Как Python нашел `5` в словаре, содержащем `5.0`? Python делает это за постоянное время без необходимости сканирования каждого элемента, используя хэш-функции. Когда Python ищет ключ `foo` в словаре, он сначала вычисляет `hash(foo)` (что выполняется в постоянном времени). Поскольку в Python требуется, чтобы объекты, которые сравниваются одинаково, имели одинаковое хэш-значение ([docs](https://docs.python.org/3/reference/datamodel.html#object.__hash__) здесь), `5`, `5.0` и `5 + 0j` имеют одинаковое хэш-значение. ```py >>> 5 == 5.0 == 5 + 0j True >>> hash(5) == hash(5.0) == hash(5 + 0j) True ``` - **Примечание:** Обратное не обязательно верно: Объекты с одинаковыми хэш-значениями сами могут быть неравными. (Это вызывает так называемую [хэш-коллизию](https://en.wikipedia.org/wiki/Collision_(computer_science)) и ухудшает производительность постоянного времени, которую обычно обеспечивает хэширование). + **Примечание:** Обратное не обязательно верно: Объекты с одинаковыми хэш-значениями сами могут быть неравными. (Это вызывает так называемую [хэш-коллизию](https://en.wikipedia.org/wiki/Collision_(computer_science)) и ухудшает производительность постоянного времени, которую обычно обеспечивает хеширование). --- @@ -604,14 +670,14 @@ class WTF: False >>> WTF() is WTF() # идентификаторы также различаются False ->>> hash(WTF()) == hash(WTF()) # хэши тоже должны отличаться +>>> hash(WTF()) == hash(WTF()) # хеши тоже должны отличаться True >>> id(WTF()) == id(WTF()) True ``` #### 💡 Объяснение: -* При вызове `id` Python создал объект класса `WTF` и передал его функции `id`. Функция `id` забирает свой `id` (местоположение в памяти) и выбрасывает объект. Объект уничтожается. +* При вызове `id` Python создал объект класса `WTF` и передал его функции `id`. Функция `id` забирает свой `id` (расположение в памяти) и выбрасывает объект. Объект уничтожается. * Когда мы делаем это дважды подряд, Python выделяет ту же самую область памяти и для второго объекта. Поскольку (в CPython) `id` использует участок памяти в качестве идентификатора объекта, идентификатор двух объектов одинаков. * Таким образом, id объекта уникален только во время жизни объекта. После уничтожения объекта или до его создания, другой объект может иметь такой же id. * Но почему выражение с оператором `is` равно `False`? Давайте посмотрим с помощью этого фрагмента. @@ -641,7 +707,7 @@ True --- -### ▶ Беспорядок внутри порядка * +### ▶ Беспорядок внутри порядка * ```py from collections import OrderedDict @@ -657,13 +723,13 @@ another_ordered_dict[2] = 'b'; another_ordered_dict[1] = 'a'; class DictWithHash(dict): """ - A dict that also implements __hash__ magic. + Словарь с реализованным методом __hash__. """ __hash__ = lambda self: 0 class OrderedDictWithHash(OrderedDict): """ - An OrderedDict that also implements __hash__ magic. + OrderedDict с реализованным методом __hash__. """ __hash__ = lambda self: 0 ``` @@ -677,7 +743,7 @@ True >>> ordered_dict == another_ordered_dict # почему же c != a ?? False -# Мы все знаем, что множество состоит только из уникальных элементов, +# Мы все знаем, что множество состоит из уникальных элементов, # давайте попробуем составить множество из этих словарей и посмотрим, что получится... >>> len({dictionary, ordered_dict, another_ordered_dict}) @@ -695,7 +761,7 @@ TypeError: unhashable type: 'dict' >>> another_ordered_dict[2] = 'b'; another_ordered_dict[1] = 'a'; >>> len({dictionary, ordered_dict, another_ordered_dict}) 1 ->>> len({ordered_dict, another_ordered_dict, dictionary}) # changing the order +>>> len({ordered_dict, another_ordered_dict, dictionary}) # изменим порядок элементов 2 ``` @@ -703,7 +769,7 @@ TypeError: unhashable type: 'dict' #### 💡 Объяснение: -- Переходное (интрантизивное) равенство между `dictionary`, `ordered_dict` и `another_ordered_dict` не выполняется из-за реализации магического метода `__eq__` в классе `OrderedDict`. Перевод цитаты из [документации](https://docs.python.org/3/library/collections.html#ordereddict-objects) +- Переходное (интранзитивное) равенство между `dictionary`, `ordered_dict` и `another_ordered_dict` не выполняется из-за реализации магического метода `__eq__` в классе `OrderedDict`. Перевод цитаты из [документации](https://docs.python.org/3/library/collections.html#ordereddict-objects) > Тесты равенства между объектами OrderedDict чувствительны к порядку и реализуются как `list(od1.items())==list(od2.items())`. Тесты на равенство между объектами `OrderedDict` и другими объектами Mapping нечувствительны к порядку, как обычные словари. - Причина такого поведения равенства в том, что оно позволяет напрямую подставлять объекты `OrderedDict` везде, где используется обычный словарь. @@ -794,7 +860,7 @@ Iteration 0 #### 💡 Объяснение: -- Когда один из операторов `return`, `break` или `continue` выполняется в блоке `try` оператора "try...finally", на выходе также выполняется пункт `finally`. +- Когда один из операторов `return`, `break` или `continue` выполняется в блоке `try` оператора "try...finally", на выходе также выполняется блок `finally`. - Возвращаемое значение функции определяется последним выполненным оператором `return`. Поскольку блок `finally` выполняется всегда, оператор `return`, выполненный в блоке `finally`, всегда будет последним. - Предостережение - если в блоке `finally` выполняется оператор `return` или `break`, то временно сохраненное исключение отбрасывается. @@ -966,7 +1032,7 @@ board = [row] * 3 [['X', '', ''], ['X', '', ''], ['X', '', '']] ``` -Мы же не назначили три `"Х"`? +Мы же не назначали три `"Х"`? #### 💡 Объяснение: @@ -1006,7 +1072,7 @@ for x in range(7): funcs_results = [func() for func in funcs] ``` -**Вывод (Python version):** +**Вывод:** ```py >>> results [0, 1, 2, 3, 4, 5, 6] @@ -1039,7 +1105,7 @@ ClosureVars(nonlocals={}, globals={'x': 6}, builtins={}, unbound=set()) [42, 42, 42, 42, 42, 42, 42] ``` -* Чтобы получить желаемое поведение, вы можете передать переменную цикла как именованную переменную в функцию. **Почему это работает?** Потому что это определит переменную *внутри* области видимости функции. Она больше не будет обращаться к глобальной области видимости для поиска значения переменной, а создаст локальную переменную, которая будет хранить значение `x` в данный момент времени. +* Чтобы получить желаемое поведение, вы можете передать переменную цикла как именованную аргумент в функцию. **Почему это работает?** Потому что это определит переменную *внутри* области видимости функции. Она больше не будет обращаться к глобальной области видимости для поиска значения переменной, а создаст локальную переменную, которая будет хранить значение `x` в данный момент времени. ```py funcs = [] @@ -1079,7 +1145,7 @@ True True ``` -Так какой же базовый класс является "окончательным"? Кстати, это еще не все, +Так какой же базовый класс является "родительским"? Кстати, это еще не все, 2\. @@ -1137,12 +1203,11 @@ False * Отношения подклассов не обязательно являются транзитивными в Python. Можно переопределить магический метод `__subclasscheck__` в метаклассе. * Когда вызывается `issubclass(cls, Hashable)`, он просто ищет не-фальшивый метод "`__hash__`" в `cls` или во всем, от чего он наследуется. -* Поскольку `object` является хэшируемым, а `list` - нехэшируемым, это нарушает отношение транзитивности. -* Более подробное объяснение можно найти [здесь] (https://www.naftaliharris.com/blog/python-subclass-intransitivity/). +* Поскольку `object` является хэшируемым, а `list` - нет, это нарушает отношение транзитивности. +* Более подробное объяснение можно найти [здесь](https://www.naftaliharris.com/blog/python-subclass-intransitivity/). --- - ### ▶ Равенство и тождество методов @@ -1202,7 +1267,7 @@ True #### 💡 Объяснение * Функции являются [дескрипторами](https://docs.python.org/3/howto/descriptor.html). Всякий раз, когда к функции обращаются как к -атрибута, вызывается дескриптор, создавая объект метода, который "связывает" функцию с объектом, владеющим атрибутом. При вызове метод вызывает функцию, неявно передавая связанный объект в качестве первого аргумента +атрибуту, вызывается дескриптор, создавая объект метода, который "связывает" функцию с объектом, владеющим атрибутом. При вызове метод вызывает функцию, неявно передавая связанный объект в качестве первого аргумента (именно так мы получаем `self` в качестве первого аргумента, несмотря на то, что не передаем его явно). ```py >>> o1.method @@ -1338,7 +1403,7 @@ True #### 💡 Объяснение -- В обычной строке обратная слэш используется для экранирования символов, которые могут иметь специальное значение (например, одинарная кавычка, двойная кавычка и сам обратный слэш). +- В обычной строке обратный слэш используется для экранирования символов, которые могут иметь специальное значение (например, одинарная кавычка, двойная кавычка и сам обратный слэш). ```py >>> "wt\"f" 'wt"f' @@ -1355,12 +1420,12 @@ True >>> print(r"\\n") '\\n' ``` -- Это означает, что когда синтаксический анализатор встречает обратный слэш в необработанной строке, он ожидает, что за ней последует другой символ. А в нашем случае (`print(r"\")`) обратная слэш экранирует двойную кавычку, оставив парсер без завершающей кавычки (отсюда `SyntaxError`). Вот почему обратный слеш не работает в конце необработанной строки. +- Это означает, что когда синтаксический анализатор встречает обратный слэш в необработанной строке, он ожидает, что за ней последует другой символ. А в нашем случае (`print(r"\")`) обратный слэш экранирует двойную кавычку, оставив синтаксический анализатор без завершающей кавычки (отсюда `SyntaxError`). Вот почему обратный слэш не работает в конце необработанной строки. --- +--- -### ▶ Не узел! (eng. not knot!) +### ▶ Не узел! (англ. not knot!) ```py x = True @@ -1383,12 +1448,12 @@ SyntaxError: invalid syntax * Старшинство операторов влияет на выполнение выражения, и оператор `==` имеет более высокий приоритет, чем оператор `not` в Python. * Поэтому `not x == y` эквивалентно `not (x == y)`, что эквивалентно `not (True == False)`, в итоге равное `True`. * Но `x == not y` вызывает `SyntaxError`, потому что его можно считать эквивалентным `(x == not) y`, а не `x == (not y)`, что можно было бы ожидать на первый взгляд. -* Парсер ожидал, что ключевое слово `not` будет частью оператора `not in` (потому что оба оператора `==` и `not in` имеют одинаковый приоритет), но после того, как он не смог найти ключевое слово `in`, следующее за `not`, он выдает `SyntaxError`. +* Синтаксический анализатор (англ. parser) ожидал, что ключевое слово `not` будет частью оператора `not in` (потому что оба оператора `==` и `not in` имеют одинаковый приоритет), но после того, как он не смог найти ключевое слово `in`, следующее за `not`, он выдает `SyntaxError`. --- -### ▶ Строки наполовину в тройных кавычках +### ▶ Строки, наполовину обернутые в тройные кавычки **Вывод:** ```py @@ -1503,7 +1568,7 @@ I have lost faith in truth! * Изначально в Python не было типа `bool` (использовали 0 для false и ненулевое значение 1 для true). В версиях 2.x были добавлены `True`, `False` и тип `bool`, но для обратной совместимости `True` и `False` нельзя было сделать константами. Они просто были встроенными переменными, и их можно было переназначить. -* Python 3 был несовместим с предыдущими версиями, эту проблему наконец-то исправили, и поэтому последний фрагмент не будет работать с Python 3.x! +* Python 3 несовместим с предыдущими версиями, эту проблему наконец-то исправили, и поэтому последний фрагмент не будет работать с Python 3.x! --- @@ -1651,7 +1716,7 @@ def some_func(x): [] ``` -То же самое, это тоже не сработало. Что происходит? +Опять не сработало. Что происходит? #### 💡 Объяснение: @@ -1659,7 +1724,7 @@ def some_func(x): > "... `return expr` в генераторе вызывает исключение `StopIteration(expr)` при выходе из генератора." -+ В случае `some_func(3)` `StopIteration` возникает в начале из-за оператора `return`. Исключение `StopIteration` автоматически перехватывается внутри обертки `list(...)` и цикла `for`. Поэтому два вышеприведенных фрагмента приводят к пустому списку. ++ В случае `some_func(3)` `StopIteration` возникает в начале из-за оператора `return`. Исключение `StopIteration` автоматически перехватывается внутри обертки `list(...)` и цикла `for`. Поэтому два вышеприведенных фрагмента возвращают пустой список. + Чтобы получить `["wtf"]` из генератора `some_func`, нужно перехватить исключение `StopIteration`. @@ -1721,7 +1786,7 @@ nan ```py >>> x = float('nan') >>> y = x / x ->>> y is y # идендичность сохраняется +>>> y is y # идентичность сохраняется True >>> y == y # сравнение ложно для y False @@ -1733,7 +1798,7 @@ True - `'inf'` и `'nan'` - это специальные строки (без учета регистра), которые при явном приведении к типу `float` используются для представления математической "бесконечности" и "не число" соответственно. -- Согласно стандартам IEEE `NaN != NaN`, но соблюдение этого правила нарушает предположение о рефлексивности элемента коллекции в Python, то есть если `x` является частью коллекции, такой как `list`, реализации, методы сравнения предполагают, что `x == x`. Поэтому при сравнении элементов сначала сравниваются их идентификаторы (так как это быстрее), а значения сравниваются только при несовпадении идентификаторов. Следующий фрагмент сделает вещи более ясными: +- Согласно стандартам IEEE, `NaN != NaN`, но соблюдение этого правила нарушает предположение о рефлексивности элемента коллекции в Python, то есть если `x` является частью коллекции, такой как `list`, реализации методов сравнения предполагают, что `x == x`. Поэтому при сравнении элементов сначала сравниваются их идентификаторы (так как это быстрее), а значения сравниваются только при несовпадении идентификаторов. Следующий фрагмент сделает вещи более ясными: ```py >>> x = float('nan') @@ -1753,7 +1818,7 @@ True --- -### ▶ Мутируем немутируемое! +### ▶ Изменяем неизменяемое! @@ -1783,8 +1848,7 @@ TypeError: 'tuple' object does not support item assignment * Перевод цитаты из [документации](https://docs.python.org/3/reference/datamodel.html) - > Неизменяемые последовательности - Объект неизменяемого типа последовательности не может измениться после создания. (Если объект содержит ссылки на другие объекты, эти объекты могут быть изменяемыми и могут быть изменены; однако набор объектов, на которые непосредственно ссылается неизменяемый объект, не может изменяться.) + > Объект неизменяемого типа последовательности не может измениться после создания. (Если объект содержит ссылки на другие объекты, эти объекты могут быть изменяемыми и могут быть изменены; однако набор объектов, на которые непосредственно ссылается неизменяемый объект, не может изменяться.) * Оператор `+=` изменяет список на месте. Присваивание элемента не работает, но когда возникает исключение, элемент уже был изменен на месте. * Также есть объяснение в официальном [Python FAQ](https://docs.python.org/3/faq/programming.html#why-does-a-tuple-i-item-raise-an-exception-when-the-addition-works). @@ -1836,30 +1900,30 @@ NameError: name 'e' is not defined del N ``` -Это означает, что исключению должно быть присвоено другое имя, чтобы на него можно было ссылаться после завершения блока `except`. Исключения очищаются, потому что с прикрепленным к ним трейсбэком они образуют цикл ссылок со стеком вызовов, сохраняя все локальные объекты в этой стэке до следующей сборки мусора. +Это означает, что исключению должно быть присвоено другое имя, чтобы на него можно было ссылаться после завершения блока `except`. Исключения очищаются, потому что с прикрепленным к ним трейсбэком они образуют цикл ссылок со стэком вызовов, сохраняя все локальные объекты в этой стэке до следующей сборки мусора. * В Python clauses не имеют области видимости. В примере все объекты в одной области видимости, а переменная `e` была удалена из-за выполнения блока `except`. Этого нельзя сказать о функциях, которые имеют отдельные внутренние области видимости. Пример ниже иллюстрирует это: -```py - def f(x): - del(x) - print(x) + ```py + def f(x): + del(x) + print(x) - x = 5 - y = [5, 4, 3] - ``` + x = 5 + y = [5, 4, 3] + ``` - **Результат:** - ```py - >>> f(x) - UnboundLocalError: local variable 'x' referenced before assignment - >>> f(y) - UnboundLocalError: local variable 'x' referenced before assignment - >>> x - 5 - >>> y - [5, 4, 3] - ``` + **Результат:** + ```py + >>> f(x) + UnboundLocalError: local variable 'x' referenced before assignment + >>> f(y) + UnboundLocalError: local variable 'x' referenced before assignment + >>> x + 5 + >>> y + [5, 4, 3] + ``` * В Python 2.x, имя переменной `e` назначается на экземпляр `Exception()`, и при попытки вывести значение `e` ничего не выводится. @@ -1954,13 +2018,9 @@ a, b = a[b] = {}, 5 > Оператор присваивания исполняет список выражений (помните, что это может быть одно выражение или список, разделенный запятыми, в последнем случае получается кортеж) и присваивает единственный результирующий объект каждому из целевых списков, слева направо. * `+` в `(target_list "=")+` означает, что может быть **один или более** целевых списков. В данном случае целевыми списками являются `a, b` и `a[b]` (обратите внимание, что список выражений ровно один, в нашем случае это `{}, 5`). - * После исполнения списка выражений его значение распаковывается в целевые списки **слева направо**. Так, в нашем случае сначала кортеж `{}, 5` распаковывается в `a, b`, и теперь у нас есть `a = {}` и `b = 5`. - * Теперь `a` имеет значение `{}`, которое является изменяемым объектом. - * Вторым целевым списком является `a[b]` (вы можете ожидать, что это вызовет ошибку, поскольку `a` и `b` не были определены в предыдущих утверждениях. Но помните, мы только что присвоили `a` значение `{}` и `b` - `5`). - * Теперь мы устанавливаем ключ `5` в словаре в кортеж `({}, 5)`, создавая круговую ссылку (`{...}` в выводе ссылается на тот же объект, на который уже ссылается `a`). Другим более простым примером круговой ссылки может быть ```py @@ -2010,7 +2070,7 @@ ValueError: Exceeds the limit (4300) for integer string conversion: #### 💡 Объяснение: Этот вызов `int()` прекрасно работает в Python 3.10.6 и вызывает ошибку `ValueError` в Python 3.10.8, 3.11. Обратите внимание, что Python все еще может работать с большими целыми числами. Ошибка возникает только при преобразовании между целыми числами и строками. К счастью, вы можете увеличить предел допустимого количества цифр. Для этого можно воспользоваться одним из следующих способов: -- `-X int_max_str_digits` - флаг командной строкиcommand-line flag +- `-X int_max_str_digits` - флаг командной строки - `set_int_max_str_digits()` - функция из модуля `sys` - `PYTHONINTMAXSTRDIGITS` - переменная окружения @@ -2230,7 +2290,7 @@ for idx, item in enumerate(list_4): >>> some_list = [1, 2, 3, 4] >>> id(some_list) 139798789457608 - >>> id(some_list[:]) # Notice that python creates new object for sliced list. + >>> id(some_list[:]) # Обратите внимание, создается новый объект из среза списка 139798779601192 ``` @@ -2239,7 +2299,7 @@ for idx, item in enumerate(list_4): * `remove` удаляет первое подходящее значение, а не конкретный индекс, вызывает `ValueError`, если значение не найдено. * `pop` удаляет элемент по определенному индексу и возвращает его, вызывает `IndexError`, если указан неверный индекс. -**Почему на выходе получается `[2, 4]`? +**Почему на выходе получается `[2, 4]`?** - Проход по списку выполняется индекс за индексом, и когда мы удаляем `1` из `list_2` или `list_4`, содержимое списков становится `[2, 3, 4]`. Оставшиеся элементы сдвинуты вниз, то есть `2` находится на индексе 0, а `3` - на индексе 1. Поскольку на следующей итерации будет просматриваться индекс 1 (который и есть `3`), `2` будет пропущен полностью. Аналогичное произойдет с каждым альтернативным элементом в последовательности списка. * Объяснение примера можно найти на [StackOverflow](https://stackoverflow.com/questions/45946228/what-happens-when-you-try-to-delete-a-list-element-while-iterating-over-it). @@ -2354,7 +2414,7 @@ print(x, ': x in global') #### 💡 Объяснение: -- В Python циклы for используют область видимости, в которой они существуют, и оставляют свою определенную переменную цикла после завершения. Это также относится к случаям, когда мы явно определили переменную цикла for в глобальном пространстве имен. В этом случае будет произведена перепривязка существующей переменной. +- В Python циклы for используют область видимости, в которой они существуют, и оставляют свою определенную переменную цикла после завершения. Это также относится к случаям, когда мы явно определили переменную цикла for в глобальном пространстве имен. В этом случае будет произведена повторная привязка существующей переменной. - Различия в выводе интерпретаторов Python 2.x и Python 3.x для примера с пониманием списков можно объяснить следующим изменением, задокументированным в журнале изменений [What's New In Python 3.0](https://docs.python.org/3/whatsnew/3.0.html): @@ -2386,7 +2446,7 @@ def some_func(default_arg=[]): #### 💡 Объяснение: -- Изменяемые аргументы функций по умолчанию в Python на самом деле не инициализируются каждый раз, когда вы вызываете функцию. Вместо этого в качестве значения по умолчанию используется недавно присвоенное им значение. Когда мы явно передали `[]` в `some_func в качестве аргумента, значение по умолчанию переменной `default_arg` не было использовано, поэтому функция вернулась, как и ожидалось. +- Изменяемые аргументы функций по умолчанию в Python на самом деле не инициализируются каждый раз, когда вы вызываете функцию. Вместо этого в качестве значения по умолчанию используется недавно присвоенное им значение. Когда мы явно передали `[]` в `some_func` в качестве аргумента, значение по умолчанию переменной `default_arg` не было использовано, поэтому функция вернулась, как и ожидалось. ```py def some_func(default_arg=[]): @@ -2396,7 +2456,7 @@ def some_func(default_arg=[]): **Результат:** ```py - >>> some_func.__defaults__ # Выражение выведет значения стандартных аргументов фукнции + >>> some_func.__defaults__ # Выражение выведет значения стандартных аргументов функции ([],) >>> some_func() >>> some_func.__defaults__ @@ -2580,7 +2640,7 @@ class SomeClass: #### 💡 Объяснение - Области видимости, вложенные внутрь определения класса, игнорируют имена, связанные на уровне класса. - Выражение-генератор имеет свою собственную область видимости. -- Начиная с версии Python 3.X, списковые вычисления также имеют свою собственную область видимости. +- Начиная с версии Python 3.X, списковые выражения (list comprehensions) также имеют свою собственную область видимости. --- @@ -2716,7 +2776,7 @@ b = "javascript" **Результат:** ```py -# assert выражение с сообщением об ошиб +# assert выражение с сообщением об ошибке >>> assert(a == b, "Both languages are different") # Исключение AssertionError не возникло ``` @@ -2939,7 +2999,7 @@ False (tuple, list) ``` -- В отличие от метода `sorted, метод `reversed` возвращает итератор. Почему? Потому что сортировка требует, чтобы итератор либо изменялся на месте, либо использовал дополнительный контейнер (список), в то время как реверсирование может работать просто путем итерации от последнего индекса к первому. +- В отличие от метода `sorted`, метод `reversed` возвращает итератор. Почему? Потому что сортировка требует, чтобы итератор либо изменялся на месте, либо использовал дополнительный контейнер (список), в то время как реверсирование может работать просто путем итерации от последнего индекса к первому. - Поэтому при сравнении `sorted(y) == sorted(y)` первый вызов `sorted()` будет потреблять итератор `y`, а следующий вызов просто вернет пустой список. @@ -2992,7 +3052,7 @@ if noon_time: Секция содержит менее известные интересные нюансы работы Python, которые неизвестны большинству новичков. -### ▶ Python, можешь ли ты помочь взлелеть? +### ▶ Python, можешь ли ты помочь взлететь? Что ж, поехали @@ -3007,7 +3067,7 @@ Sshh... It's a super-secret. + Модуль `antigravity` - одно из немногих пасхальных яиц, выпущенных разработчиками Python. + `import antigravity` открывает веб-браузер, указывающий на [классический комикс XKCD](https://xkcd.com/353/) о Python. -+ Это еще не все. Внутри пасхального яйца находится **еще одно пасхальное яйцо**. Если вы посмотрите на [код](https://github.com/python/cpython/blob/master/Lib/antigravity.py#L7-L17), там определена функция, которая якобы реализует [алгоритм геохашинга XKCD](https://xkcd.com/426/). ++ Это еще не все. Внутри пасхального яйца находится **еще одно пасхальное яйцо**. Если вы посмотрите на [код](https://github.com/python/cpython/blob/master/Lib/antigravity.py#L7-L17), там определена функция, которая якобы реализует алгоритм [XKCD](https://xkcd.com/426/). --- @@ -3164,7 +3224,7 @@ True ### ▶ Да, оно существует! -**Ключевое слово `else` в связвке с циклом `for`.** Один из стандартных примеров: +**Ключевое слово `else` в связке с циклом `for`.** Один из стандартных примеров: ```py def does_exists_num(l, to_find): @@ -3239,7 +3299,7 @@ Ellipsis - Многоточие может использоваться в нескольких случаях, + В качестве заполнителя для кода, который еще не написан (аналогично оператору `pass`) + В синтаксисе срезов (slices) для представления полных срезов в оставшемся направлении - ``py + ```py >>> import numpy as np >>> three_dimensional_array = np.arange(8).reshape(2, 2, 2) array([ @@ -3264,7 +3324,7 @@ Ellipsis [5, 7]]) ``` Примечание: это будет работать для любого количества измерений. Можно даже выбрать срез в первом и последнем измерении и игнорировать средние (`n_dimensional_array[firs_dim_slice, ..., last_dim_slice]`) - + В [подсказках типов](https://docs.python.org/3/library/typing.html) для указания только части типа (например, `(Callable[..., int]` или `Tuple[str, ...]`)) + + В [подсказках типов](https://docs.python.org/3/library/typing.html) для указания только части типа (например, `Callable[..., int]` или `Tuple[str, ...]`) + Вы также можете использовать `Ellipsis` в качестве аргумента функции по умолчанию (в случаях, когда вы хотите провести различие между сценариями "аргумент не передан" и "значение не передано"). --- @@ -3483,7 +3543,7 @@ def square(x): ## Секция: Разное -### ▶ `+=` быстрее +### ▶ `+=` быстрее `+` ```py @@ -3587,7 +3647,7 @@ def convert_list_to_string(l, iters): >>> %timeit -n100 add_string_with_plus(1000) 388 µs ± 22.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each) - >>> %timeit -n100 add_string_with_plus(10000) # Quadratic increase in execution time + >>> %timeit -n100 add_string_with_plus(10000) # Квадратичное увеличение времени выполнения 9 ms ± 298 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) ``` @@ -3627,7 +3687,7 @@ KeyError: 1 #### 💡 Объяснение: + В CPython есть общая функция поиска по словарю, которая работает со всеми типами ключей (`str`, `int`, любой объект ...), и специализированная для распространенного случая словарей, состоящих только из `str`-ключей. -+ Специализированная функция (названная `lookdict_unicode` в [исходный код CPython](https://github.com/python/cpython/blob/522691c46e2ae51faaad5bbbce7d959dd61770df/Objects/dictobject.c#L841)) знает, что все существующие ключи (включая искомый ключ) являются строками, и использует более быстрое и простое сравнение строк для сравнения ключей, вместо вызова метода `__eq__`. ++ Специализированная функция (названная `lookdict_unicode` в [CPython](https://github.com/python/cpython/blob/522691c46e2ae51faaad5bbbce7d959dd61770df/Objects/dictobject.c#L841)) знает, что все существующие ключи (включая искомый ключ) являются строками, и использует более быстрое и простое сравнение строк для сравнения ключей, вместо вызова метода `__eq__`. + При первом обращении к экземпляру `dict` с ключом, не являющимся `str`, он модифицируется, чтобы в дальнейшем для поиска использовалась общая функция. + Этот процесс не обратим для конкретного экземпляра `dict`, и ключ даже не обязательно должен существовать в словаре. Поэтому попытка неудачного поиска имеет тот же эффект. @@ -3706,7 +3766,7 @@ def dict_size(o): * Несколько странных, но семантически правильных утверждений: + `[] = ()` - семантически корректное утверждение (распаковка пустого `кортежа` в пустой `список`) - + `'a'[0][0][0][0][0]` также является семантически корректным утверждением, поскольку в Python строки являются [последовательностями](https://docs.python.org/3/glossary.html#term-sequence)(итерируемыми объектами, поддерживающими доступ к элементам с использованием целочисленных индексов). + + `'a'[0][0][0][0][0]` также является семантически корректным утверждением, поскольку в Python строки являются [последовательностями](https://docs.python.org/3/glossary.html#term-sequence) (итерируемыми объектами, поддерживающими доступ к элементам с использованием целочисленных индексов). + `3 --0-- 5 == 8` и `--5 == 5` - оба семантически корректные утверждения и имеют значение `True`. * Учитывая, что `a` - это число, `++a` и `--a` являются корректными утверждениями Python, но ведут себя не так, как аналогичные утверждения в таких языках, как C, C++ или Java.