wtfpython/translations/README-ru.md

10 KiB
Raw Blame History

What the f*ck Python! 😱

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

Переводы: English Original Chinese 中文 | Vietnamese Tiếng Việt | Spanish Español | Korean 한국어 | Russian Русский | German Deutsch | Add translation

Альтернативные способы: Интерактивный сайт | Интерактивный Jupiter notebook | CLI

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

wtfpython задуман как проект, пытающийся объяснить, что именно происходит под капотом некоторых неочевидных фрагментов кода и менее известных возможностей Python.

Если вы опытный программист на Python, вы можете принять это как вызов и правильно объяснить WTF ситуации с первой попытки. Возможно, вы уже сталкивались с некоторыми из них раньше, и я смогу оживить ваши старые добрые воспоминания! 😅

PS: Если вы уже читали wtfpython раньше, с изменениями можно ознакомиться здесь (примеры, отмеченные звездочкой - это примеры, добавленные в последней основной редакции).

Ну что ж, приступим...

Содержание

Структура примера

Все примеры имеют следующую структуру:

▶ Какой-то заголовок

# Неочевидный фрагмент кода
# Подготовка к магии...

Вывод (Python версия):

>>> triggering_statement
Неожиданные результаты

(Опционально): Краткое описание неожиданного результата

💡 Объяснение

  • Краткое объяснение того, что происходит и почему это происходит.
# Код
# Дополнительные примеры для дальнейшего разъяснения (если необходимо)

Вывод (Python версия):

>>> trigger # какой-нибудь пример, позволяющий легко раскрыть магию
# обоснованный вывод

Важно: Все примеры протестированы на интерактивном интерпретаторе Python 3.5.2, и они должны работать для всех версий Python, если это явно не указано перед выводом.

Применение

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

  • Внимательно изучить исходный код. Если вы опытный программист на Python, то в большинстве случаев сможете предугадать, что произойдет дальше.
  • Прочитать фрагменты вывода и,
    • Проверить, совпадают ли выходные данные с вашими ожиданиями.
    • Убедиться, что вы знаете точную причину, по которой вывод получился именно таким.
      • Если ответ отрицательный (что совершенно нормально), сделать глубокий вдох и прочитать объяснение (а если пример все еще непонятен, и создайте issue здесь).
      • Если "да", ощутите мощь своих познаний в Python и переходите к следующему примеру.

PS: Вы также можете читать WTFPython в командной строке, используя pypi package,

pip install wtfpython -U
wtfpython

👀 Примеры

Секция: Напряги мозги!

▶ Первым делом!

По какой-то причине "моржовый оператор" (англ. walrus) := в Python 3.8 стал довольно популярным. Давайте проверим его,

1.

# Python version 3.8+

>>> a = "wtf_walrus"
>>> a
'wtf_walrus'

>>> a := "wtf_walrus"
File "<stdin>", line 1
    a := "wtf_walrus"
      ^
SyntaxError: invalid syntax

>>> (a := "wtf_walrus") # А этот код работает
'wtf_walrus'
>>> a
'wtf_walrus'

2 .

# Python version 3.8+

>>> a = 6, 9
>>> a
(6, 9)

>>> (a := 6, 9)
(6, 9)
>>> a
6

>>> a, b = 6, 9 # Типичная распаковка
>>> a, b
(6, 9)
>>> (a, b = 16, 19) # Упс
  File "<stdin>", line 1
    (a, b = 16, 19)
          ^
SyntaxError: invalid syntax

>>> (a, b := 16, 19) # На выводе получаем странный кортеж из 3 элементов
(6, 16, 19)

>>> a # Значение переменной остается неизменной?
6

>>> b
16

💡 Обьяснение

Быстрый разбор что такое "моржовый оператор"

"Моржовый оператор" (:=) был представлен в Python 3.8, может быть полезен в ситуациях, когда вы хотите присвоить значения переменным в выражении.

def some_func():
    # Предположим, что здесь выполняются требовательные к ресурсам вычисления
    # time.sleep(1000)
    return 5

# Поэтому вместо,
if some_func():
    print(some_func()) # Плохая практика, поскольку вычисления происходят дважды.

# Или
a = some_func()
if a:
    print(a)

# Можно лаконично написать
if a := some_func():
    print(a)

Вывод (> 3.8):

5
5
5

Использование := сэкономило одну строку кода и неявно предотвратило вызов some_func дважды.

  • "выражение присваивания", не обернутое в скобки, иначе говоря использование моржового оператора, ограничено на верхнем уровне, отсюда SyntaxError в выражении a := "wtf_walrus" в первом фрагменте. После оборачивания в скобки, a было присвоено значение, как и ожидалось.

  • В то же время оборачивание скобками выражения, содержащего оператор =, не допускается. Отсюда синтаксическая ошибка в (a, b = 6, 9).

  • Синтаксис моржового оператора имеет вид NAME:= expr, где NAME - допустимый идентификатор, а expr - допустимое выражение. Следовательно, упаковка и распаковка итерируемых объектов не поддерживается, что означает,

    • (a := 6, 9) эквивалентно ((a := 6), 9) и в конечном итоге (a, 9) (где значение a равно 6)

      >>> (a := 6, 9) == ((a := 6), 9)
      True
      >>> x = (a := 696, 9)
      >>> x
      (696, 9)
      >>> x[0] is a # Оба ссылаются на одну и ту же ячейку памяти
      True
      
    • Аналогично, (a, b := 16, 19) эквивалентно (a, (b := 16), 19), которое есть не что иное, как кортеж из 3 элементов.