Профілювання та оптимізація коду ред.

У стандартній бібліотеці Python є профайлер (модуль profile), який можна використовувати для збору статистики про час роботи окремих функцій. Для вирішення питання про те, який варіант коду працює швидше, можна використовувати модуль timeit. Виміри, що проводяться в наступній програмі дозволяють з'ясувати, який з варіантів конкатенації рядків більш ефективний:

from timeit import Timer
def case1(): # А. інкрементального конкатенації в циклі
    s = ""
    for i in range(10000):
        s += str(i)

def case2(): # Б. через проміжний список і метод join
    s = []
    for i in range(10000):
        s.append(str(i))
    s = "".join(s)

def case3(): # В. спискового вираз і метод join
    return "".join([str(i) for i in range(10000)])

def case4(): # Г. генераторні вираз і метод join
    return "".join(str(i) for i in range(10000))

for v in range(1,5):
    print (Timer("func()","from __main__ import case%s as func" % v).timeit(200))

Як і в будь-якій мові програмування, у Python є свої прийоми оптимізації коду. Оптимізувати код можна, виходячи з різних (часто конкуруючих між собою) критеріїв (збільшення швидкодії, зменшення обсягу необхідної оперативної пам'яті, компактність вихідного коду і т. д.). Найчастіше програми оптимізують за часом виконання.

Тут є кілька очевидних правил:

  • Не потрібно оптимізувати програму, якщо швидкість її виконання достатня.
  • Використовуваний алгоритм має певну тимчасову складність, тому перед оптимізацією коду програми варто спочатку переглянути алгоритм.
  • Варто використовувати готові і налагоджені функції та модулі, навіть якщо для цього потрібно небагато обробити дані. Наприклад, у Python є вбудована функція sort().
  • Профілювання допоможе з'ясувати вузькі місця. Оптимізацію потрібно починати з них.

Python має такі особливості і пов'язані з ними правила оптимізації:

  • Виклик функцій є досить дорогою операцією, тому всередині вкладених циклів потрібно прагнути уникати виконання функцій або, наприклад, переносити цикл у функції. Функція, обробна послідовність, ефективніша, ніж обробка тієї ж послідовності у циклі з викликом функції.
  • Намагайтеся винести з глибоко вкладеного циклу все, що можна обчислити в зовнішніх циклах. Доступ до локальних змінних більш швидкий, ніж до глобальних, або ніж доступ до полів.
  • Оптимізатор psyco може допомогти прискорити роботу модулю програми за умови, що модуль не використовує динамічних властивостей мови Python.
  • У випадку, якщо модуль проводить масивну обробку даних і оптимізація алгоритму та коду не допомагає, можна переписати критичні ділянки, скажімо, на мові Сі або Cython.

Інструмент під назвою Pychecker[1] допоможе проаналізувати вихідний код на Python та видати рекомендації згідно зі знайденими проблемами (наприклад, невикористані імена, зміна сигнатури методу при його перевантаженні тощо). В ході такого статичного аналізу вихідного коду можуть бути виявлені і помилки. Pylint[2] покликаний вирішувати близькі завдання але більш схиляється до перевірки стилю коду.


  1. PyChecker: a python source code checking tool
  2. pylint (analyzes Python source code looking for bugs and signs of poor quality.) (Logilab.org)