Peephole - это способ, которым Python оптимизирует определенные элементы вашей программы во время компиляции, либо предварительно вычисляя константные выражения, либо преобразовывая определенные структуры данных.

Постоянные выражения

Оптимизировать постоянные выражения действительно просто. Python в основном предварительно вычисляет константы. Предположим, что в вашей программе по какой-то причине используется следующее умножение:

secondsInADay = 60*60*24

Python предварительно вычислит это умножение и заменит его на 86400. Вам может быть интересно, почему бы просто не написать 86400 прямо в коде, ответ - ясность. В приведенном выше выражении вы можете видеть, что для того, чтобы рассчитать, сколько секунд в день, вам нужно умножить 60 секунд, 60 минут на час, на 24 часа в сутки. Таким образом ваш код может выглядеть яснее. Python не будет производить это вычисление каждый раз, когда появляется умножение, он просто предварительно вычислит его и заменит на окончательное значение.

Короткие последовательности также предварительно рассчитываются. Представьте, что у вас есть этот код,

myTuple = (2, 4)*5      # -> (2, 4, 2, 4, 2, 4, 2, 4, 2, 4)
myString = "qwerty "*2  # -> "qwerty qwerty "

Как вы можете видеть в приведенном выше коде, у нас есть две переменные, первая - это кортеж, умноженный на 5, а второй - короткая строка, умноженная на 2, эти короткие последовательности будут предварительно рассчитаны, и Python заменит исходное выражение на значение в комментариях. Стоит упомянуть, что Python должен балансировать между хранением и вычислением. Если он предварительно вычисляет длинные последовательности, программа может быть быстрее, но в конечном итоге будет использовать много памяти.

Чтобы увидеть, что это происходит, вы можете просто открыть консоль Python и написать следующий код:

def my_func():
    a = 60*60*24
    myString = ("querty ") * 2
    myTupple = (2, 4) *5
    myString = ("This is a sequence with a lot of characters") * 100

После объявления этой функции вы можете написать следующий код для доступа ко всем константам, объявленным в области видимости этой функции,

my_func.__code__.co_consts

Результат должен быть следующим:

>>> my_func.__code__.co_consts
(None, 
86400, 
'querty querty ', 
(2, 4, 2, 4, 2, 4, 2, 4, 2, 4), 
'This is a sequence with a lot of characters', 
100)

Как вы можете видеть, в выходных данных выше Python уже предварительно рассчитал постоянные значения и короткие последовательности, вместо того, чтобы иметь 60*60*24, функция уже имеет постоянное значение 86400, то же самое происходит с кортежем и короткой строкой, но как вы можно увидеть, что длинная последовательность не была рассчитана заранее, и вместо этого мы получаем две разные константы, 'This is a sequence with a lot of characters' и 100. Как упоминалось выше, Python должен балансировать между хранением и вычислением.

Тесты на членство: замена изменяемых структур данных на неизменяемые структуры данных

Python в основном преобразует изменяемые структуры данных в неизменяемую версию. Списки преобразуются в кортежи, а наборы - в frozensets.

Например,

def my_func(element):
    if element in ["a", "b", "c"]:
        print(element)

Приведенный выше код будет преобразован в это,

def my_func(element):
    if element in ("a", "b", "c"):
        print(element)

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

my_func.__code__.co_consts

Результат должен быть следующим:

>>> my_func.__code__.co_consts
(None, ('a', 'b', 'c'))

Как видите, функция имеет постоянное значение, которое является неизменной версией (кортеж) объявленного списка.

Наконец, сделав то же самое, что и раньше, но с set, вы увидите, что он будет преобразован в frozenset,

def my_func(element):
    if element in {"a", "b", "c"}:
        print(element)
>>> my_func.__code__.co_consts
(None, frozenset({'a', 'b', 'c'}))

Если вас интересует оптимизация Python, вы можете прочитать мою статью Оптимизация Python (Intering).