Наступил 2020 год, а значит, Python 2 перестал поддерживаться. Если быть совсем точным, то основные разработчики уже перестали заниматься веткой, а выход релиза 2.7.18, приуроченный к PyCon US в апреле 2020 года, ознаменует полное прекращение любой активности, связанной с Python 2.


С другой стороны, совсем недавно состоялся релиз Python 3.8, добавивший немного синтаксического сахара в язык. Python 3.9 же ожидается ещё нескоро, да и пока не похоже что добавит в язык что-то интересное.


Так что если вы вдруг ещё не отказались от Python 2, то дальше тянуть смысла просто нет: поддержка второй версии уже прекратилась, а переход сразу на 3.8 позволит использовать язык в его самом актуальном состоянии ещё долгое время.


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


1. Выражения присваивания (Assignment expressions)


Так же известные как «моржовый оператор» (walrus operator) — новый синтаксис, который позволит присваивать значения переменным внутри другого выражения. Это, наверное, самое известное и обсуждаемое из нововведений версии 3.8.


a = 6

# Код ниже присваивает b значение a ** 2
# и проверяет, если b > 0
if (b := a ** 2) > 0: 
    print(f'Квадрат {a} это {b}.') # Квадрат 6 это 36.

Целью введения оператора является повышение читаемости кода, поэтому использовать его (как и все остальные операторы) стоит не при первой же возможности, а только тогда, когда это уместно.


# так делать НЕ НАДО
a = 5
d = [b := a+1, a := b-1, a := a*2]

2. Только позиционные аргументы


Функции могут принимать два типа аргументов.


  • Позиционные — передаваемые по позиции
  • Именованные — передаваемые по имени

В коде ниже, значения обоих аргументов a и b можно передать как по позиции, так и по имени.


def my_func(a, b=1):
    return a+b

my_func(5,2)      # Оба аргумента позиционные
my_func(a=5, b=2) # Оба аргумента именованные

В новой версии Питона можно явно ограничить, какие из параметров могут быть только позиционными или только именованными с помощью символов /  и *  в сигнатуре функции (последний, правда, появился ещё до Python 3.8).


В примере ниже, первые два параметра a и b только позиционные, c и d могут быть любыми, а последние два e и f должны быть именованными.


def my_func(a, b, /, c, d, *, e, f):
    return a+b+c+d+e+f
  
my_func(1, 2, 3, 4, 5, 6)         # ошибка: e, f должны быть именованными
my_func(a=1, b=2, 3, 4, e=5, f=6) # ошибка: a, b должны быть позиционными
my_func(1, 2, c=3, 4, e=5, f=6)   # returns 21
my_unc(1, 2, c=3, d=4, e=5, f=6)  # returns 21

Зачем же ограничивать гибкость типов аргументов? В некоторых случаях использование имени параметра вместо его позиции будет бесполезным и неуместным. Ограничение так же позволит избежать проблем, если вы планируете изменить имена позиционных аргументов в будущем.


3. f-строки 2.0


Сложно описать словами, насколько проще и элегантнее сделали форматирование f-строки, появившиеся ещё в Python 3.6.


Сложно поверить, но Python 3.8 удалось сделать их ещё удобнее. Добавив знак = после имени подставляемой переменной, вы сможете вывести её имя и её значение без дублирования имени.


pi = 3  # В военное время может быть и так

print(f'pi={pi}')  # так мы делали раньше
print(f'{pi=}')     # а так можно делать теперь

Дебаг с помощью print станет ещё удобнее :)


4. Обратный порядок элементов словаря


Итерироваться по словарям теперь можно в обратном порядке с помощью reversed().


5. Получение метаданных из других модулей


Новый модуль importlib.metadata позволит получать метаданные (например, версию) из сторонних пакетов.


6. finally + continue


Раньше нельзя было использовать выражение continue внутри finally из-за сложности в реализации этой фичи. Теперь можно. 


for i in range(2):
    try:
        print(i)
    finally:
        print('Тест.')
        continue
        print('Эту строку вы не увидите.')

# Python <= 3.7
>> SyntaxError: 'continue' not supported inside 'finally' clause
  
# Python 3.8
>> 0
   Тест.
   1
   Тест.