Документация Python неофициальный перевод

programming.md

1662 строк · 133.4 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/2.7/faq/programming.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# [ЧЗВ по программированию](https://python-all.ru/2.7/faq/programming.html#id1)89Содержание1011- [Вопросы по программированию](https://python-all.ru/2.7/faq/programming.html#programming-faq)1213  - [Общие вопросы](https://python-all.ru/2.7/faq/programming.html#general-questions)1415    - [Существует ли отладчик на уровне исходного кода с точками останова, пошаговым выполнением и т. д.?](https://python-all.ru/2.7/faq/programming.html#is-there-a-source-code-level-debugger-with-breakpoints-single-stepping-etc)16    - [Существует ли инструмент для поиска ошибок или выполнения статического анализа?](https://python-all.ru/2.7/faq/programming.html#is-there-a-tool-to-help-find-bugs-or-perform-static-analysis)17    - [Как создать автономный исполняемый файл из скрипта Python?](https://python-all.ru/2.7/faq/programming.html#how-can-i-create-a-stand-alone-binary-from-a-python-script)18    - [Существуют ли стандарты кодирования или руководство по стилю для программ на Python?](https://python-all.ru/2.7/faq/programming.html#are-there-coding-standards-or-a-style-guide-for-python-programs)19    - [Моя программа слишком медленная. Как её ускорить?](https://python-all.ru/2.7/faq/programming.html#my-program-is-too-slow-how-do-i-speed-it-up)20  - [Ядро языка](https://python-all.ru/2.7/faq/programming.html#core-language)2122    - [Почему возникает UnboundLocalError, если переменная имеет значение?](https://python-all.ru/2.7/faq/programming.html#why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value)23    - [Каковы правила для локальных и глобальных переменных в Python?](https://python-all.ru/2.7/faq/programming.html#what-are-the-rules-for-local-and-global-variables-in-python)24    - [Почему лямбда-функции, определённые в цикле с разными значениями, возвращают один и тот же результат?](https://python-all.ru/2.7/faq/programming.html#why-do-lambdas-defined-in-a-loop-with-different-values-all-return-the-same-result)25    - [Как разделять глобальные переменные между модулями?](https://python-all.ru/2.7/faq/programming.html#how-do-i-share-global-variables-across-modules)26    - [Каковы «лучшие практики» использования import в модуле?](https://python-all.ru/2.7/faq/programming.html#what-are-the-best-practices-for-using-import-in-a-module)27    - [Почему значения по умолчанию разделяются между объектами?](https://python-all.ru/2.7/faq/programming.html#why-are-default-values-shared-between-objects)28    - [Как передать необязательные или именованные параметры из одной функции в другую?](https://python-all.ru/2.7/faq/programming.html#how-can-i-pass-optional-or-keyword-parameters-from-one-function-to-another)29    - [В чём разница между аргументами и параметрами?](https://python-all.ru/2.7/faq/programming.html#what-is-the-difference-between-arguments-and-parameters)30    - [Почему изменение списка 'y' также изменило список 'x'?](https://python-all.ru/2.7/faq/programming.html#why-did-changing-list-y-also-change-list-x)31    - [Как написать функцию с выходными параметрами (передача по ссылке)?](https://python-all.ru/2.7/faq/programming.html#how-do-i-write-a-function-with-output-parameters-call-by-reference)32    - [Как создать функцию высшего порядка в Python?](https://python-all.ru/2.7/faq/programming.html#how-do-you-make-a-higher-order-function-in-python)33    - [Как скопировать объект в Python?](https://python-all.ru/2.7/faq/programming.html#how-do-i-copy-an-object-in-python)34    - [Как найти методы или атрибуты объекта?](https://python-all.ru/2.7/faq/programming.html#how-can-i-find-the-methods-or-attributes-of-an-object)35    - [Как моему коду узнать имя объекта?](https://python-all.ru/2.7/faq/programming.html#how-can-my-code-discover-the-name-of-an-object)36    - [Что не так с приоритетом оператора запятой?](https://python-all.ru/2.7/faq/programming.html#what-s-up-with-the-comma-operator-s-precedence)37    - [Существует ли эквивалент тернарного оператора «?:» из C?](https://python-all.ru/2.7/faq/programming.html#is-there-an-equivalent-of-c-s-ternary-operator)38    - [Можно ли писать запутанные однострочники на Python?](https://python-all.ru/2.7/faq/programming.html#is-it-possible-to-write-obfuscated-one-liners-in-python)39  - [Числа и строки](https://python-all.ru/2.7/faq/programming.html#numbers-and-strings)4041    - [Как указать шестнадцатеричные и восьмеричные целые числа?](https://python-all.ru/2.7/faq/programming.html#how-do-i-specify-hexadecimal-and-octal-integers)42    - [Почему -22 // 10 возвращает -3?](https://python-all.ru/2.7/faq/programming.html#why-does-22-10-return-3)43    - [Как преобразовать строку в число?](https://python-all.ru/2.7/faq/programming.html#how-do-i-convert-a-string-to-a-number)44    - [Как преобразовать число в строку?](https://python-all.ru/2.7/faq/programming.html#how-do-i-convert-a-number-to-a-string)45    - [Как изменить строку на месте?](https://python-all.ru/2.7/faq/programming.html#how-do-i-modify-a-string-in-place)46    - [Как с помощью строк вызывать функции и методы?](https://python-all.ru/2.7/faq/programming.html#how-do-i-use-strings-to-call-functions-methods)47    - [Существует ли аналог функции chomp() из Perl для удаления завершающих символов новой строки из строк?](https://python-all.ru/2.7/faq/programming.html#is-there-an-equivalent-to-perl-s-chomp-for-removing-trailing-newlines-from-strings)48    - [Существует ли аналог функций scanf() или sscanf()?](https://python-all.ru/2.7/faq/programming.html#is-there-a-scanf-or-sscanf-equivalent)49    - [Что означает ошибка «UnicodeError: ASCII \[decoding,encoding\] error: ordinal not in range(128)»?](https://python-all.ru/2.7/faq/programming.html#what-does-unicodeerror-ascii-decoding-encoding-error-ordinal-not-in-range-128-mean)50  - [Последовательности (кортежи/списки)](https://python-all.ru/2.7/faq/programming.html#sequences-tuples-lists)5152    - [Как преобразовывать кортежи в списки и обратно?](https://python-all.ru/2.7/faq/programming.html#how-do-i-convert-between-tuples-and-lists)53    - [Что такое отрицательный индекс?](https://python-all.ru/2.7/faq/programming.html#what-s-a-negative-index)54    - [Как перебрать последовательность в обратном порядке?](https://python-all.ru/2.7/faq/programming.html#how-do-i-iterate-over-a-sequence-in-reverse-order)55    - [Как удалить дубликаты из списка?](https://python-all.ru/2.7/faq/programming.html#how-do-you-remove-duplicates-from-a-list)56    - [Как создать массив в Python?](https://python-all.ru/2.7/faq/programming.html#how-do-you-make-an-array-in-python)57    - [Как создать многомерный список?](https://python-all.ru/2.7/faq/programming.html#how-do-i-create-a-multidimensional-list)58    - [Как применить метод к последовательности объектов?](https://python-all.ru/2.7/faq/programming.html#how-do-i-apply-a-method-to-a-sequence-of-objects)59    - [Почему a\_tuple\[i\] += \[‘item’\] вызывает исключение, хотя само сложение работает?](https://python-all.ru/2.7/faq/programming.html#why-does-a-tuple-i-item-raise-an-exception-when-the-addition-works)60  - [Словари](https://python-all.ru/2.7/faq/programming.html#dictionaries)6162    - [Как сделать так, чтобы ключи словаря отображались в постоянном порядке?](https://python-all.ru/2.7/faq/programming.html#how-can-i-get-a-dictionary-to-display-its-keys-in-a-consistent-order)63    - [Я хочу выполнить сложную сортировку: можно ли в Python реализовать преобразование Шварца?](https://python-all.ru/2.7/faq/programming.html#i-want-to-do-a-complicated-sort-can-you-do-a-schwartzian-transform-in-python)64    - [Как отсортировать один список по значениям из другого списка?](https://python-all.ru/2.7/faq/programming.html#how-can-i-sort-one-list-by-values-from-another-list)65  - [Объекты](https://python-all.ru/2.7/faq/programming.html#objects)6667    - [Что такое класс?](https://python-all.ru/2.7/faq/programming.html#what-is-a-class)68    - [Что такое метод?](https://python-all.ru/2.7/faq/programming.html#what-is-a-method)69    - [Что такое self?](https://python-all.ru/2.7/faq/programming.html#what-is-self)70    - [Как проверить, является ли объект экземпляром данного класса или его подкласса?](https://python-all.ru/2.7/faq/programming.html#how-do-i-check-if-an-object-is-an-instance-of-a-given-class-or-of-a-subclass-of-it)71    - [Что такое делегирование?](https://python-all.ru/2.7/faq/programming.html#what-is-delegation)72    - [Как вызвать метод, определённый в базовом классе, из производного класса, который его переопределяет?](https://python-all.ru/2.7/faq/programming.html#how-do-i-call-a-method-defined-in-a-base-class-from-a-derived-class-that-overrides-it)73    - [Как организовать код, чтобы было проще изменить базовый класс?](https://python-all.ru/2.7/faq/programming.html#how-can-i-organize-my-code-to-make-it-easier-to-change-the-base-class)74    - [Как создать статические данные класса и статические методы класса?](https://python-all.ru/2.7/faq/programming.html#how-do-i-create-static-class-data-and-static-class-methods)75    - [Как перегрузить конструкторы (или методы) в Python?](https://python-all.ru/2.7/faq/programming.html#how-can-i-overload-constructors-or-methods-in-python)76    - [Я пытаюсь использовать \_\_spam и получаю ошибку о \_SomeClassName\_\_spam.](https://python-all.ru/2.7/faq/programming.html#i-try-to-use-spam-and-i-get-an-error-about-someclassname-spam)77    - [Мой класс определяет \_\_del\_\_, но он не вызывается при удалении объекта.](https://python-all.ru/2.7/faq/programming.html#my-class-defines-del-but-it-is-not-called-when-i-delete-the-object)78    - [Как получить список всех экземпляров данного класса?](https://python-all.ru/2.7/faq/programming.html#how-do-i-get-a-list-of-all-instances-of-a-given-class)79    - [Почему результат `id()` не является уникальным?](https://python-all.ru/2.7/faq/programming.html#why-does-the-result-of-id-appear-to-be-not-unique)80  - [Модули](https://python-all.ru/2.7/faq/programming.html#modules)8182    - [Как создать .pyc-файл?](https://python-all.ru/2.7/faq/programming.html#how-do-i-create-a-pyc-file)83    - [Как узнать имя текущего модуля?](https://python-all.ru/2.7/faq/programming.html#how-do-i-find-the-current-module-name)84    - [Как сделать так, чтобы модули импортировали друг друга?](https://python-all.ru/2.7/faq/programming.html#how-can-i-have-modules-that-mutually-import-each-other)85    - [\_\_import\_\_(‘x.y.z’) возвращает \<module ‘x’\>; как получить z?](https://python-all.ru/2.7/faq/programming.html#import-x-y-z-returns-module-x-how-do-i-get-z)86    - [При редактировании импортированного модуля и его повторном импорте изменения не отображаются. Почему это происходит?](https://python-all.ru/2.7/faq/programming.html#when-i-edit-an-imported-module-and-reimport-it-the-changes-don-t-show-up-why-does-this-happen)8788## [Общие вопросы](https://python-all.ru/2.7/faq/programming.html#id2)8990### [Существует ли отладчик на уровне исходного кода с точками останова, пошаговым выполнением и т. д.?](https://python-all.ru/2.7/faq/programming.html#id3)9192Да.9394Модуль pdb – это простой, но достаточный консольный отладчик для Python. Он является частью стандартной библиотеки Python и [`documented in the Library Reference Manual`](https://python-all.ru/2.7/library/pdb.html#module-pdb). Вы также можете написать собственный отладчик, используя код pdb в качестве примера.9596Интерактивная среда разработки IDLE, которая входит в стандартную установку Python (обычно доступна как Tools/scripts/idle), включает графический отладчик.9798PythonWin – это IDE для Python, включающая графический отладчик на основе pdb. Отладчик Pythonwin подсвечивает точки останова и обладает рядом полезных возможностей, таких как отладка программ, не относящихся к Pythonwin. PythonWin доступен как часть проекта [Python for Windows Extensions](https://python-all.ru/2.7/faq/programming.html) и как часть дистрибутива ActivePython (см. [https://www.activestate.com/activepython](https://python-all.ru/2.7/faq/programming.html)).99100[Boa Constructor](https://python-all.ru/2.7/faq/programming.html) – это среда разработки и конструктор графического интерфейса на основе wxWidgets. Он предоставляет визуальное создание и редактирование фреймов, инспектор объектов, различные представления исходного кода, включая обозреватели объектов, иерархии наследования, HTML-документацию, сгенерированную из строк документации, расширенный отладчик, встроенную справку и поддержку Zope.101102[Eric](https://python-all.ru/2.7/faq/programming.html) – это IDE, построенная на PyQt и компоненте редактирования Scintilla.103104Pydb – это версия стандартного отладчика Python pdb, модифицированная для использования с DDD (Data Display Debugger), популярным графическим интерфейсом отладчика. Pydb можно найти по адресу [http://bashdb.sourceforge.net/pydb/](https://python-all.ru/2.7/faq/programming.html), а DDD – по адресу [https://www.gnu.org/software/ddd](https://python-all.ru/2.7/faq/programming.html).105106Существует ряд коммерческих IDE для Python, включающих графические отладчики. Среди них:107108- Wing IDE ([https://wingware.com/](https://python-all.ru/2.7/faq/programming.html))109- Komodo IDE ([https://komodoide.com/](https://python-all.ru/2.7/faq/programming.html))110- PyCharm ([https://www.jetbrains.com/pycharm/](https://python-all.ru/2.7/faq/programming.html))111112### [Существует ли инструмент для поиска ошибок или выполнения статического анализа?](https://python-all.ru/2.7/faq/programming.html#id4)113114Да.115116PyChecker – это инструмент статического анализа, который находит ошибки в исходном коде Python и предупреждает о сложности и стиле кода. PyChecker можно получить по адресу [http://pychecker.sourceforge.net/](https://python-all.ru/2.7/faq/programming.html).117118[Pylint](https://python-all.ru/2.7/faq/programming.html) – это ещё один инструмент, который проверяет, соответствует ли модуль стандарту кодирования, а также позволяет писать плагины для добавления собственных возможностей. В дополнение к проверке ошибок, выполняемой PyChecker, Pylint предлагает некоторые дополнительные функции, такие как проверка длины строк, соответствие имён переменных вашему стандарту кодирования, полная реализация объявленных интерфейсов и многое другое. На [https://docs.pylint.org/](https://python-all.ru/2.7/faq/programming.html) представлен полный список возможностей Pylint.119120### [Как создать автономный исполняемый файл из скрипта Python?](https://python-all.ru/2.7/faq/programming.html#id5)121122Вам не нужно уметь компилировать Python в C, если ваша цель – создать автономную программу, которую пользователи могут скачать и запустить без предварительной установки дистрибутива Python. Существует ряд инструментов, которые определяют набор модулей, необходимых программе, и связывают эти модули вместе с бинарным файлом Python, создавая единый исполняемый файл.123124Один из способов – использовать инструмент freeze, который включён в дерево исходных текстов Python как `Tools/freeze`. Он преобразует байт-код Python в C-массивы; с помощью C-компилятора можно встроить все свои модули в новую программу, которая затем компонуется со стандартными модулями Python.125126Он работает, рекурсивно сканируя ваш исходный код на наличие операторов import (в обеих формах) и ищет модули в стандартном пути Python, а также в каталоге исходного кода (для встроенных модулей). Затем он превращает байт-код модулей, написанных на Python, в код C (инициализаторы массивов, которые можно превратить в объекты кода с помощью модуля marshal) и создает специальный конфигурационный файл, содержащий только те встроенные модули, которые действительно используются в программе. После этого он компилирует сгенерированный код C и компонует его с остальной частью интерпретатора Python, формируя самодостаточный бинарный файл, который ведет себя точно так же, как ваш скрипт.127128Очевидно, freeze требует компилятор C. Существует несколько других утилит, которые не требуют. Одна из них – py2exe Томаса Хеллера (только для Windows) по адресу129130> [http://www.py2exe.org/](https://python-all.ru/2.7/faq/programming.html)131132Другой инструмент – [cx\_Freeze](https://python-all.ru/2.7/faq/programming.html) Энтони Туйнинги.133134### [Существуют ли стандарты кодирования или руководство по стилю для программ на Python?](https://python-all.ru/2.7/faq/programming.html#id6)135136Да. Требуемый стиль оформления кода для модулей стандартной библиотеки описан в документе [**PEP 8**](https://python-all.ru/2.7/faq/programming.html).137138### [Моя программа слишком медленная. Как её ускорить?](https://python-all.ru/2.7/faq/programming.html#id7)139140В целом, ответить непросто. Существует множество приёмов для ускорения Python-кода; переписывание частей на C стоит рассматривать лишь как крайнюю меру.141142В некоторых случаях Python можно автоматически преобразовать в C или ассемблер x86, а значит, для повышения быстродействия не требуется изменять код.143144[Pyrex](https://python-all.ru/2.7/faq/programming.html) позволяет компилировать немного изменённую версию кода Python в расширение C и работает на множестве различных платформ.145146[Psyco](https://python-all.ru/2.7/faq/programming.html) – это JIT-компилятор, транслирующий код Python в ассемблер x86. При возможности использования Psyco может существенно ускорить выполнение критических функций.147148В оставшейся части ответа будут рассмотрены различные приёмы для извлечения дополнительной скорости из кода Python. *Никогда* не следует применять какие-либо оптимизации, если не известно, что они нужны, и только после того, как профилирование показало, что конкретная функция является наиболее часто выполняемым узким местом в коде. Оптимизации почти всегда снижают понятность кода, и не стоит платить цену снижения ясности (увеличение времени разработки, большая вероятность ошибок), если только результирующий выигрыш в производительности того не стоит.149150На вики есть страница, посвящённая [советам по производительности](https://python-all.ru/2.7/faq/programming.html).151152Гвидо ван Россум написал заметку об оптимизации по адресу [https://www.python.org/doc/essays/list2str](https://python-all.ru/2.7/faq/programming.html).153154Стоит заметить, что вызовы функций и (особенно) методов довольно дороги; если вы спроектировали чисто объектно-ориентированный интерфейс с множеством крошечных функций, которые делают не больше, чем получают или устанавливают переменную экземпляра или вызывают другой метод, возможно, стоит использовать более прямой способ, например прямой доступ к переменным экземпляра. Также см. стандартный модуль [`profile`](https://python-all.ru/2.7/library/profile.html#module-profile), который позволяет узнать, где ваша программа проводит большую часть времени (если у вас есть терпение – само профилирование может замедлить программу на порядок).155156Следует помнить, что многие стандартные эвристики оптимизации, известные из другого опыта программирования, применимы и к Python. Например, отправка вывода на устройства вывода более крупными порциями может быть быстрее, чем мелкими, так как снижаются накладные расходы на системные вызовы ядра. Поэтому CGI-скрипты, выводящие всё за один раз, могут быть быстрее тех, что выводят много маленьких фрагментов.157158Также стоит использовать основные возможности Python там, где это уместно. Например, срезы позволяют программам разрезать списки и другие объекты-последовательности за один такт главного цикла интерпретатора благодаря высокооптимизированным реализациям на C. Итак, чтобы получить тот же эффект, что и:159160```python161L2 = []162for i in range(3):163    L2.append(L1[i])164```165166гораздо короче и намного быстрее использовать167168```python169L2 = list(L1[:3])  # "list" избыточен, если L1 является списком.170```171172Обратите внимание, что встроенные функции функционального стиля, такие как [`map()`](https://python-all.ru/2.7/library/functions.html#map), [`zip()`](https://python-all.ru/2.7/library/functions.html#zip) и им подобные, могут быть удобным ускорителем для циклов, выполняющих одну задачу. Например, чтобы попарно объединить элементы двух списков:173174```python175>>> zip([1, 2, 3], [4, 5, 6])176[(1, 4), (2, 5), (3, 6)]177```178179или для вычисления нескольких синусов:180181```python182>>> map(math.sin, (1, 2, 3, 4))183[0.841470984808, 0.909297426826, 0.14112000806, -0.756802495308]184```185186В таких случаях операция выполняется очень быстро.187188Другие примеры включают `join()` и `split()` [методы строковых объектов](https://python-all.ru/2.7/library/stdtypes.html#string-methods). Например, если s1..s7 – большие строки (10 КБ и более), то `"".join([s1,s2,s3,s4,s5,s6,s7])` может быть значительно быстрее, чем более очевидное `s1+s2+s3+s4+s5+s6+s7`, поскольку «суммирование» вычисляет много промежуточных результатов, тогда как `join()` выполняет всё копирование за один проход. Для работы со строками используйте `replace()` и `format()` [методы строковых объектов](https://python-all.ru/2.7/library/stdtypes.html#string-methods). Используйте регулярные выражения, только когда не имеете дела с постоянными строковыми шаблонами. Можно также использовать [старые операции с %](https://python-all.ru/2.7/library/stdtypes.html#string-formatting) `string % tuple` и `string % dictionary`.189190Обязательно используйте встроенный метод `list.sort()` для сортировки и загляните в [мини-HOWTO по сортировке](https://python-all.ru/2.7/faq/programming.html) с примерами умеренно продвинутого использования. `list.sort()` превосходит другие методы сортировки во всех, кроме самых крайних случаев.191192Ещё один распространённый приём – «выносить циклы в функции или методы». Например, предположим, у вас есть программа, которая работает медленно, и вы используете профайлер, чтобы определить, что функция Python `ff()` вызывается очень часто. Если вы замечаете, что `ff()`:193194```python195def ff(x):196    ... # выполнить действия с x, вычисляя результат...197    return result198```199200склонна вызываться в циклах наподобие:201202```python203list = map(ff, oldlist)204```205206или:207208```python209for x in sequence:210    value = ff(x)211    ... # выполнить действия со значением...212```213214тогда вы часто можете устранить накладные расходы на вызов функции, переписав `ff()` так:215216```python217def ffseq(seq):218    resultseq = []219    for x in seq:220        ... # выполнить действия с x, вычисляя результат...221        resultseq.append(result)222    return resultseq223```224225и перепишите два примера как `list = ffseq(oldlist)` и как:226227```python228for value in ffseq(sequence):229    ... # выполнить действия со значением...230```231232Одиночные вызовы `ff(x)` превращаются в `ffseq([x])[0]` с небольшими потерями. Конечно, этот приём подходит не всегда, и есть другие варианты, которые вы можете придумать.233234Можно повысить производительность, явно сохраняя результаты поиска функции или метода в локальной переменной. Цикл наподобие:235236```python237for key in token:238    dict[key] = dict.get(key, 0) + 1239```240241разрешает `dict.get` на каждой итерации. Если метод не будет меняться, немного более быстрая реализация:242243```python244dict_get = dict.get  # найти метод один раз245for key in token:246    dict[key] = dict_get(key, 0) + 1247```248249Аргументы по умолчанию можно использовать для однократного определения значений на этапе компиляции, а не во время выполнения. Это возможно только для функций или объектов, которые не будут изменяться во время выполнения программы, например замена250251```python252def degree_sin(deg):253    return math.sin(deg * math.pi / 180.0)254```255256на257258```python259def degree_sin(deg, factor=math.pi/180.0, sin=math.sin):260    return sin(deg * factor)261```262263Поскольку этот приём использует аргументы по умолчанию для значений, которые не должны изменяться, его следует использовать только в тех случаях, когда не нужно беспокоиться о том, что API может оказаться запутанным для пользователей.264265## [Ядро языка](https://python-all.ru/2.7/faq/programming.html#id8)266267### [Почему возникает UnboundLocalError, если переменная содержит значение?](https://python-all.ru/2.7/faq/programming.html#id9)268269Может быть неожиданным получить ошибку UnboundLocalError в ранее работавшем коде после добавления оператора присваивания где-то в теле функции.270271Этот код:272273```python274>>> x = 10275>>> def bar():276...     print x277>>> bar()27810279```280281работает, но этот код:282283```python284>>> x = 10285>>> def foo():286...     print x287...     x += 1288```289290приводит к ошибке UnboundLocalError:291292```python293>>> foo()294Traceback (most recent call last):295  ...296UnboundLocalError: local variable 'x' referenced before assignment297```298299Это происходит потому, что при присваивании значения переменной в некоторой области видимости эта переменная становится локальной для данной области и затеняет любую одноимённую переменную из внешней области. Поскольку последний оператор в foo присваивает новое значение `x`, компилятор считает её локальной переменной. Следовательно, когда предыдущий `print x` пытается вывести на печать неинициализированную локальную переменную, возникает ошибка.300301В приведённом выше примере можно получить доступ к переменной внешней области, объявив её глобальной:302303```python304>>> x = 10305>>> def foobar():306...     global x307...     print x308...     x += 1309>>> foobar()31010311```312313Такое явное объявление необходимо, чтобы напомнить: в отличие от внешне похожей ситуации с переменными класса и экземпляра, здесь фактически изменяется значение переменной во внешней области видимости:314315```python316>>> print x31711318```319320### [Каковы правила использования локальных и глобальных переменных в Python?](https://python-all.ru/2.7/faq/programming.html#id10)321322В Python переменные, на которые только ссылаются внутри функции, неявно считаются глобальными. Если переменной присваивается значение где-либо в теле функции, она считается локальной, если явно не объявлена как global.323324Хотя поначалу это может показаться удивительным, небольшое размышление объясняет такое поведение. С одной стороны, требование [`global`](https://python-all.ru/2.7/reference/simple_stmts.html#global) для присваиваемых переменных служит барьером против непреднамеренных побочных эффектов. С другой стороны, если бы `global` требовалось для всех глобальных ссылок, пришлось бы постоянно использовать `global`. Пришлось бы объявлять как global каждую ссылку на встроенную функцию или компонент импортированного модуля. Такая избыточность свела бы на нет пользу объявления `global` для выявления побочных эффектов.325326### [Почему лямбды, определённые в цикле с разными значениями, все возвращают один и тот же результат?](https://python-all.ru/2.7/faq/programming.html#id11)327328Предположим, что с помощью цикла for определяется несколько разных лямбд (или даже обычных функций), например:329330```python331>>> squares = []332>>> for x in range(5):333...     squares.append(lambda: x**2)334```335336Это даёт список, содержащий 5 лямбд, вычисляющих `x**2`. Можно ожидать, что при вызове они вернут соответственно `0`, `1`, `4`, `9` и `16`. Однако при попытке вызова обнаружится, что все они возвращают `16`:337338```python339>>> squares[2]()34016341>>> squares[4]()34216343```344345Это происходит потому, что `x` не является локальной для лямбд, а определена во внешней области видимости, и обращение к ней происходит при вызове лямбды, а не при её определении. В конце цикла значение `x` равно `4`, поэтому все функции теперь возвращают `4**2`, то есть `16`. Это можно также проверить, изменив значение `x` и посмотрев, как изменятся результаты лямбд:346347```python348>>> x = 8349>>> squares[2]()35064351```352353Чтобы избежать этого, необходимо сохранить значения в переменных, локальных для лямбд, чтобы они не зависели от значения глобальной `x`:354355```python356>>> squares = []357>>> for x in range(5):358...     squares.append(lambda n=x: n**2)359```360361Здесь `n=x` создаёт новую переменную `n`, локальную для лямбды и вычисляемую при её определении, так что она имеет то же значение, которое `x` имела в этот момент в цикле. Это означает, что значение `n` будет равно `0` в первой лямбде, `1` – во второй, `2` – в третьей и так далее. Следовательно, теперь каждая лямбда будет возвращать правильный результат:362363```python364>>> squares[2]()3654366>>> squares[4]()36716368```369370Обратите внимание: такое поведение присуще не только лямбдам, но и обычным функциям.371372### [Как разделять глобальные переменные между модулями?](https://python-all.ru/2.7/faq/programming.html#id12)373374Общепринятый способ обмена информацией между модулями в рамках одной программы – создать специальный модуль (часто называемый config или cfg). Достаточно импортировать модуль config во все модули приложения, и он станет доступен как глобальное имя. Поскольку у каждого модуля существует только один экземпляр, любые изменения объекта модуля отражаются везде. Например:375376config.py:377378```python379x = 0   # Значение по умолчанию для параметра конфигурации 'x'380```381382mod.py:383384```python385import config386config.x = 1387```388389main.py:390391```python392import config393import mod394print config.x395```396397Обратите внимание: использование модуля также является основой для реализации паттерна Singleton по той же причине.398399### [Каковы «лучшие практики» использования import в модуле?](https://python-all.ru/2.7/faq/programming.html#id13)400401В целом не стоит использовать `from modulename import *`. Это захламляет пространство имён импортёра и сильно усложняет линтерам обнаружение неопределённых имён.402403Импортируйте модули в начале файла. Так сразу становится ясно, какие ещё модули требуются вашему коду, и не возникает вопросов, находится ли имя модуля в области видимости. Использование одного импорта на строку упрощает добавление и удаление импортов, а использование нескольких импортов в одной строке экономит место на экране.404405Рекомендуется импортировать модули в следующем порядке:4064071. модули стандартной библиотеки – например `sys`, `os`, `getopt`, `re`4082. модули сторонних библиотек (всё, установленное в каталог site-packages Python), например mx.DateTime, ZODB, PIL.Image и т.д.4093. модули локальной разработки410411Используйте только явные относительные импорты пакетов. Если вы пишете код, который находится в модуле `package.sub.m1`, и хотите импортировать `package.sub.m2`, не пишите просто `import m2`, хотя это и допустимо. Вместо этого пишите `from package.sub import m2` или `from . import m2`.412413Иногда импорты приходится переносить внутрь функции или класса, чтобы избежать проблем с циклическими импортами. Gordon McMillan говорит:414415> Циклические импорты нормально работают, когда оба модуля используют форму импорта “import \<module\>”. Они перестают работать, когда второй модуль пытается получить имя из первого (“from module import name”), и импорт находится на верхнем уровне. Это происходит потому, что имена в первом модуле ещё недоступны, так как первый модуль занят импортом второго.416417В этом случае, если второй модуль используется только в одной функции, импорт можно легко перенести в эту функцию. К моменту вызова импорта первый модуль уже завершит инициализацию, и второй модуль сможет выполнить свой импорт.418419Также может потребоваться перенести импорты из верхнего уровня кода, если некоторые модули являются платформозависимыми. В таком случае может быть невозможно импортировать все модули в начале файла. Тогда хорошим решением будет импортировать нужные модули в соответствующем платформозависимом коде.420421Переносите импорты в локальную область видимости, например в определение функции, только если это необходимо для решения проблемы – избежания циклического импорта или сокращения времени инициализации модуля. Этот приём особенно полезен, когда многие импорты не нужны в зависимости от того, как выполняется программа. Также можно перенести импорты в функцию, если модули используются только в ней. Обратите внимание: первая загрузка модуля может быть дорогой из-за однократной инициализации, но повторные загрузки практически бесплатны и требуют лишь пары словарных поисков. Даже если имя модуля вышло из области видимости, сам модуль, скорее всего, доступен в [`sys.modules`](https://python-all.ru/2.7/library/sys.html#sys.modules).422423### [Почему значения по умолчанию являются общими для объектов?](https://python-all.ru/2.7/faq/programming.html#id14)424425Подобная ошибка часто подстерегает начинающих программистов. Рассмотрим следующую функцию:426427```python428def foo(mydict={}):  # Опасность: общая ссылка на один словарь для всех вызовов429    ... compute something ...430    mydict[key] = value431    return mydict432```433434При первом вызове этой функции `mydict` содержит один элемент. При втором вызове `mydict` содержит уже два элемента, потому что когда `foo()` начинает выполняться, `mydict` уже содержит один элемент.435436Часто ожидается, что при вызове функции для значений по умолчанию создаются новые объекты. Но это не так. Значения по умолчанию создаются ровно один раз, при определении функции. Если этот объект изменяется (как словарь в данном примере), то последующие вызовы функции будут обращаться к этому изменённому объекту.437438По определению, неизменяемые объекты – числа, строки, кортежи и `None` – защищены от изменений. Изменения изменяемых объектов, таких как словари, списки и экземпляры классов, могут приводить к путанице.439440Из-за этой особенности рекомендуется не использовать изменяемые объекты в качестве значений по умолчанию. Вместо этого используйте `None` в качестве значения по умолчанию, а внутри функции проверяйте, равен ли параметр `None`, и при необходимости создавайте новый список, словарь и т.д. Например, не пишите:441442```python443def foo(mydict={}):444    ...445```446447а:448449```python450def foo(mydict=None):451    if mydict is None:452        mydict = {}  # создать новый словарь для локального пространства имён453```454455Эта возможность может быть полезной. Если есть функция, вычисление которой требует много времени, распространённый приём – кэшировать параметры и результат каждого вызова функции, а при повторном запросе тех же значений возвращать сохранённый результат. Это называется «мемоизация» и может быть реализовано так:456457```python458# Вызывающие никогда не передадут третий параметр этой функции.459def expensive(arg1, arg2, _cache={}):460    if (arg1, arg2) in _cache:461        return _cache[(arg1, arg2)]462463    # Вычислить значение464    result = ... expensive computation ...465    _cache[(arg1, arg2)] = result           # Сохранить результат в кеше466    return result467```468469Вместо значения по умолчанию можно использовать глобальную переменную со словарём; это дело вкуса.470471### [Как передать необязательные или именованные параметры из одной функции в другую?](https://python-all.ru/2.7/faq/programming.html#id15)472473Соберите аргументы с помощью спецификаторов `*` и `**` в списке параметров функции; это даст позиционные аргументы в виде кортежа, а именованные – в виде словаря. Затем вы можете передать эти аргументы при вызове другой функции, используя `*` и `**`:474475```python476def f(x, *args, **kwargs):477    ...478    kwargs['width'] = '14.3c'479    ...480    g(x, *args, **kwargs)481```482483В маловероятном случае, если вас заботят версии Python старше 2.0, используйте [`apply()`](https://python-all.ru/2.7/library/functions.html#apply):484485```python486def f(x, *args, **kwargs):487    ...488    kwargs['width'] = '14.3c'489    ...490    apply(g, (x,)+args, kwargs)491```492493### [В чём разница между аргументами и параметрами?](https://python-all.ru/2.7/faq/programming.html#id16)494495[Параметры](https://python-all.ru/2.7/glossary.html#term-parameter) определяются именами, которые указаны в определении функции, тогда как [аргументы](https://python-all.ru/2.7/glossary.html#term-argument) – это значения, которые передаются функции при её вызове. Параметры определяют, какие типы аргументов может принимать функция. Например, для такого определения функции:496497```python498def func(foo, bar=None, **kwargs):499    pass500```501502*foo*, *bar* и *kwargs* являются параметрами функции `func`. Однако при вызове `func`, например:503504```python505func(42, bar=314, extra=somevar)506```507508значения `42`, `314` и `somevar` являются аргументами.509510### [Почему изменение списка ‘y’ также изменило список ‘x’?](https://python-all.ru/2.7/faq/programming.html#id17)511512Если вы написали такой код:513514```python515>>> x = []516>>> y = x517>>> y.append(10)518>>> y519[10]520>>> x521[10]522```523524вас может интересовать, почему добавление элемента к `y` изменило и `x`.525526К этому результату приводят два фактора:5275281. Переменные – это просто имена, ссылающиеся на объекты. Операция `y = x` не создаёт копию списка – она создаёт новую переменную `y`, которая ссылается на тот же объект, что и `x`. Это означает, что существует только один объект (список), и обе переменные `x` и `y` ссылаются на него.5292. Списки являются [изменяемыми](https://python-all.ru/2.7/glossary.html#term-mutable), то есть их содержимое можно изменять.530531После вызова `append()` содержимое изменяемого объекта\\nизменилось с `[]` на `[10]`. Поскольку обе переменные ссылаются на один и тот же объект, использование любого имени даёт доступ к изменённому значению `[10]`.532533Если же присвоить неизменяемый объект `x`:534535```python536>>> x = 5  # int – неизменяемый тип537>>> y = x538>>> x = x + 1  # 5 нельзя изменить, здесь создаётся новый объект539>>> x5406541>>> y5425543```544545в этом случае `x` и `y` уже не равны. Это\\nпотому, что целые числа [неизменяемы](https://python-all.ru/2.7/glossary.html#term-immutable), и когда мы делаем `x = x + 1`, мы не\\nизменяем int `5`, увеличивая его значение; вместо этого мы создаём\\nновый объект (int `6`) и присваиваем его `x` (то есть изменяем, на какой объект ссылается `x`). После этого присваивания у нас есть два объекта (int `6` и `5`) и две переменные, ссылающиеся на них (`x` теперь ссылается на `6`, а `y` всё ещё ссылается на `5`).546547Некоторые операции (например `y.append(10)` и `y.sort()`) изменяют\\nобъект, тогда как внешне похожие операции (например `y = y + [10]`\\nи `sorted(y)`) создают новый объект. В общем случае в Python (и во всех случаях\\nв стандартной библиотеке) метод, изменяющий объект, возвращает `None`,\\nчтобы избежать путаницы между двумя типами операций. Так что если вы\\nошибочно напишете `y.sort()`, думая, что получите отсортированную копию `y`,\\nто вместо этого получите `None`, что, скорее всего, приведёт к легко диагностируемой ошибке в вашей программе.548549Однако есть один класс операций, где одна и та же операция иногда\\nведёт себя по-разному с разными типами: составные операторы присваивания.\\nНапример, `+=` изменяет списки, но не кортежи или целые числа (`a_list += [1, 2, 3]` эквивалентно `a_list.extend([1, 2, 3])` и изменяет\\n`a_list`, тогда как `some_tuple += (1, 2, 3)` и `some_int += 1` создают\\nновые объекты).550551Иными словами:552553- Если у нас есть изменяемый объект (`list`, [`dict`](https://python-all.ru/2.7/library/stdtypes.html#dict), [`set`](https://python-all.ru/2.7/library/stdtypes.html#set), и т. д.), можно использовать некоторые специфические операции для его изменения, и все переменные, которые на него ссылаются, увидят это изменение.554- Если у нас есть неизменяемый объект ([`str`](https://python-all.ru/2.7/library/functions.html#str), [`int`](https://python-all.ru/2.7/library/functions.html#int), [`tuple`](https://python-all.ru/2.7/library/functions.html#tuple), и т. д.), все переменные, которые на него ссылаются, всегда будут видеть одно и то же значение, но операции, преобразующие это значение в новое, всегда возвращают новый объект.555556Чтобы узнать, ссылаются ли две переменные на один и тот же объект, можно\\nиспользовать оператор [`is`](https://python-all.ru/2.7/reference/expressions.html#is) или встроенную функцию [`id()`](https://python-all.ru/2.7/library/functions.html#id).557558### [Как написать функцию с выходными параметрами (передача по ссылке)?](https://python-all.ru/2.7/faq/programming.html#id18)559560Помните, что в Python аргументы передаются по присваиванию. Поскольку присваивание лишь создает ссылки на объекты, между именем аргумента в вызывающей и вызываемой функции нет псевдонима, а значит, нет и передачи по ссылке как таковой. Желаемого эффекта можно достичь несколькими способами.5615621. Возвращая кортеж результатов:563564   ```python565   def func2(a, b):566       a = 'new-value'        # a и b – локальные имена567       b = b + 1              # присвоены новым объектам568       return a, b            # вернуть новые значения569570   x, y = 'old-value', 99571   x, y = func2(x, y)572   print x, y                 # вывод: new-value 100573   ```574575   Это почти всегда самое понятное решение.5762. С помощью глобальных переменных. Это не потокобезопасно и не рекомендуется.5773. Передавая изменяемый (изменяемый на месте) объект:578579   ```python580   def func1(a):581       a[0] = 'new-value'     # 'a' ссылается на изменяемый список582       a[1] = a[1] + 1        # изменяет общий объект583584   args = ['old-value', 99]585   func1(args)586   print args[0], args[1]     # вывод: new-value 100587   ```5884. Передавая словарь, который будет изменён:589590   ```python591   def func3(args):592       args['a'] = 'new-value'     # args – изменяемый словарь593       args['b'] = args['b'] + 1   # изменить его на месте594595   args = {'a': 'old-value', 'b': 99}596   func3(args)597   print args['a'], args['b']598   ```5995. Или объединив значения в экземпляре класса:600601   ```python602   class callByRef:603       def __init__(self, **args):604           for (key, value) in args.items():605               setattr(self, key, value)606607   def func4(args):608       args.a = 'new-value'        # args – изменяемый callByRef609       args.b = args.b + 1         # изменить объект на месте610611   args = callByRef(a='old-value', b=99)612   func4(args)613   print args.a, args.b614   ```615616   Почти никогда нет веской причины усложнять до такой степени.617618Лучший выбор – вернуть кортеж, содержащий несколько результатов.619620### [Как сделать функцию высшего порядка в Python?](https://python-all.ru/2.7/faq/programming.html#id19)621622У вас есть два варианта: использовать вложенные области видимости или вызываемые объекты.\\nНапример, предположим, вы хотите определить `linear(a,b)`, которая возвращает\\nфункцию `f(x)`, вычисляющую значение `a*x+b`. Используя вложенные области видимости:623624```python625def linear(a, b):626    def result(x):627        return a * x + b628    return result629```630631Или используя вызываемый объект:632633```python634class linear:635636    def __init__(self, a, b):637        self.a, self.b = a, b638639    def __call__(self, x):640        return self.a * x + self.b641```642643В обоих случаях644645```python646taxes = linear(0.3, 2)647```648649даёт вызываемый объект, где `taxes(10e6) == 0.3 * 10e6 + 2`.650651Подход с вызываемым объектом имеет недостаток: он немного медленнее и\\nприводит к чуть более длинному коду. Однако обратите внимание, что набор вызываемых объектов\\nможет разделять свою сигнатуру через наследование:652653```python654class exponential(linear):655    # __init__ унаследован656    def __call__(self, x):657        return self.a * (x ** self.b)658```659660Объект может инкапсулировать состояние для нескольких методов:661662```python663class counter:664665    value = 0666667    def set(self, x):668        self.value = x669670    def up(self):671        self.value = self.value + 1672673    def down(self):674        self.value = self.value - 1675676count = counter()677inc, dec, reset = count.up, count.down, count.set678```679680Здесь `inc()`, `dec()` и `reset()` ведут себя как функции, которые разделяют одну\\nи ту же переменную счётчика.681682### [Как скопировать объект в Python?](https://python-all.ru/2.7/faq/programming.html#id20)683684В общем случае для копирования попробуйте [`copy.copy()`](https://python-all.ru/2.7/library/copy.html#copy.copy) или [`copy.deepcopy()`](https://python-all.ru/2.7/library/copy.html#copy.deepcopy).\\nНе все объекты можно копировать, но большинство можно.685686Некоторые объекты можно скопировать проще. У словарей есть метод [`copy()`](https://python-all.ru/2.7/library/stdtypes.html#dict.copy):687688```python689newdict = olddict.copy()690```691692Последовательности можно скопировать срезом:693694```python695new_l = l[:]696```697698### [Как найти методы или атрибуты объекта?](https://python-all.ru/2.7/faq/programming.html#id21)699700Для экземпляра x пользовательского класса `dir(x)` возвращает отсортированный по алфавиту список имён, содержащий атрибуты экземпляра, методы и атрибуты, определённые в его классе.701702### [Как код может узнать имя объекта?](https://python-all.ru/2.7/faq/programming.html#id22)703704Вообще говоря, нет, потому что у объектов на самом деле нет имён. По сути, присваивание всегда связывает имя со значением; то же верно для операторов `def` и `class`, но в этом случае значением является вызываемый объект. Рассмотрим следующий код:705706```python707>>> class A:708...     pass709...710>>> B = A711>>> a = B()712>>> b = a713>>> print b714<__main__.A instance at 0x16D07CC>715>>> print a716<__main__.A instance at 0x16D07CC>717```718719Можно утверждать, что у класса есть имя: даже если он привязан к двум именам и вызывается через имя B, созданный экземпляр всё равно будет определён как экземпляр класса A. Однако невозможно сказать, какое имя у экземпляра – a или b, поскольку оба имени привязаны к одному и тому же значению.720721Вообще говоря, коду не требуется «знать имена» конкретных значений. Если вы не пишете намеренно интроспективные программы, это обычно указывает на то, что стоит изменить подход.722723В comp.lang.python Фредрик Лунд однажды привёл отличную аналогию в ответ на этот вопрос:724725> Так же, как вы узнаёте имя кота, которого нашли на крыльце: сам кот (объект) не может сказать вам своё имя, да ему всё равно – поэтому единственный способ выяснить, как его зовут, – спросить всех соседей (пространства имён), не их ли это кот (объект)…726>727> …и не удивляйтесь, если окажется, что он известен под многими именами или вообще без имени!728729### [Что не так с приоритетом оператора-запятой?](https://python-all.ru/2.7/faq/programming.html#id23)730731Запятая в Python – не оператор. Рассмотрим такой сеанс:732733```python734>>> "a" in "b", "a"735(False, 'a')736```737738Поскольку запятая – не оператор, а разделитель между выражениями, приведённый выше код выполняется так, как если бы вы ввели:739740```python741("a" in "b"), "a"742```743744а не:745746```python747"a" in ("b", "a")748```749750То же самое верно для различных операторов присваивания (`=`, `+=` и т. д.). Они не являются операторами в полном смысле, а представляют собой синтаксические разделители в операторах присваивания.751752### [Существует ли аналог тернарного оператора «?:» из C?](https://python-all.ru/2.7/faq/programming.html#id24)753754Да, эта возможность была добавлена в Python 2.5. Синтаксис выглядел бы так:755756```python757[on_true] if [expression] else [on_false]758759x, y = 50, 25760761small = x if x < y else y762```763764Для версий до 2.5 ответ был бы «Нет».765766### [Можно ли писать запутанные однострочники на Python?](https://python-all.ru/2.7/faq/programming.html#id25)767768Да. Обычно это делается вложением [`lambda`](https://python-all.ru/2.7/reference/expressions.html#lambda) внутрь [`lambda`](https://python-all.ru/2.7/reference/expressions.html#lambda). См. следующие три примера, предоставленные Ульфом Бартельтом:769770```python771# Простые числа < 1000772print filter(None,map(lambda y:y*reduce(lambda x,y:x*y!=0,773map(lambda x,y=y:y%x,range(2,int(pow(y,0.5)+1))),1),range(2,1000)))774775# Первые 10 чисел Фибоначчи776print map(lambda x,f=lambda x,f:(f(x-1,f)+f(x-2,f)) if x>1 else 1: f(x,f),777range(10))778779# Множество Мандельброта780print (lambda Ru,Ro,Iu,Io,IM,Sx,Sy:reduce(lambda x,y:x+y,map(lambda y,781Iu=Iu,Io=Io,Ru=Ru,Ro=Ro,Sy=Sy,L=lambda yc,Iu=Iu,Io=Io,Ru=Ru,Ro=Ro,i=IM,782Sx=Sx,Sy=Sy:reduce(lambda x,y:x+y,map(lambda x,xc=Ru,yc=yc,Ru=Ru,Ro=Ro,783i=i,Sx=Sx,F=lambda xc,yc,x,y,k,f=lambda xc,yc,x,y,k,f:(k<=0)or (x*x+y*y784>=4.0) or 1+f(xc,yc,x*x-y*y+xc,2.0*x*y+yc,k-1,f):f(xc,yc,x,y,k,f):chr(78564+F(Ru+x*(Ro-Ru)/Sx,yc,0,0,i)),range(Sx))):L(Iu+y*(Io-Iu)/Sy),range(Sy786))))(-2.1, 0.7, -1.2, 1.2, 30, 80, 24)787#    \___ ___/  \___ ___/  |   |   |__ линии на экране788#        V          V      |   |______ столбцы на экране789#        |          |      |__________ максимум "iterations"790#        |          |_________________ диапазон по оси Y791#        |____________________________ диапазон по оси X792```793794Не пытайтесь повторить это дома, дети!795796## [Числа и строки](https://python-all.ru/2.7/faq/programming.html#id26)797798### [Как задать шестнадцатеричные и восьмеричные целые числа?](https://python-all.ru/2.7/faq/programming.html#id27)799800Чтобы задать восьмеричное число, поставьте перед восьмеричным значением ноль, а затем строчную или прописную букву «o». Например, чтобы присвоить переменной «a» восьмеричное значение «10» (8 в десятичной системе), введите:801802```python803>>> a = 0o10804>>> a8058806```807808Шестнадцатеричные числа задаются так же просто. Просто поставьте перед шестнадцатеричным числом ноль, а затем строчную или прописную «x». Шестнадцатеричные цифры можно указывать в нижнем или верхнем регистре. Например, в интерпретаторе Python:809810```python811>>> a = 0xa5812>>> a813165814>>> b = 0XB2815>>> b816178817```818819### [Почему -22 // 10 возвращает -3?](https://python-all.ru/2.7/faq/programming.html#id28)820821В первую очередь это вызвано желанием, чтобы `i % j` имел тот же знак, что и `j`. Если вы хотите этого, а также хотите:822823```python824i == (i // j) * j + (i % j)825```826827тогда целочисленное деление должно возвращать пол (округление вниз). Язык C также требует выполнения этого тождества, и тогда компиляторы, усекающие `i // j`, должны делать так, чтобы `i % j` имел тот же знак, что и `i`.828829Существует мало реальных применений `i % j`, когда `j` отрицательно. Когда `j` положительно, применений много, и практически во всех из них полезнее, чтобы `i % j` было `>= 0`. Если часы показывают 10 сейчас, что они показывали 200 часов назад? `-190 % 12 == 2` полезно; `-190 % 12 == -10` – это ошибка, которая только и ждёт, чтобы её допустили.830831> **Примечание**832>833> В Python 2 `a / b` возвращает то же, что и `a // b`, если `__future__.division` не действует. Это также известно как «классическое» деление.834835### [Как преобразовать строку в число?](https://python-all.ru/2.7/faq/programming.html#id29)836837Для целых чисел используйте встроенный конструктор типа [`int()`](https://python-all.ru/2.7/library/functions.html#int), например `int('144') == 144`. Аналогично, [`float()`](https://python-all.ru/2.7/library/functions.html#float) преобразует в число с плавающей запятой, например `float('144') == 144.0`.838839По умолчанию они интерпретируют число как десятичное, поэтому `int('0144') == 144` и `int('0x144')` вызывают [`ValueError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.ValueError). `int(string, base)` принимает основание системы счисления для преобразования как второй необязательный аргумент, так что `int('0x144', 16) == 324`. Если основание указано как 0, число интерпретируется по правилам Python: ведущий ‘0’ означает восьмеричное, а ‘0x’ – шестнадцатеричное.840841Не используйте встроенную функцию [`eval()`](https://python-all.ru/2.7/library/functions.html#eval), если нужно просто преобразовать строку в число. [`eval()`](https://python-all.ru/2.7/library/functions.html#eval) будет работать значительно медленнее и создаёт угрозу безопасности: кто-то может передать Python-выражение с нежелательными побочными эффектами. Например, можно передать `__import__('os').system("rm -rf $HOME")`, что приведёт к удалению вашего домашнего каталога.842843[`eval()`](https://python-all.ru/2.7/library/functions.html#eval) также интерпретирует числа как выражения Python, так что, например, `eval('09')` вызывает синтаксическую ошибку, поскольку Python считает числа, начинающиеся с ‘0’, восьмеричными (основание 8).844845### [Как преобразовать число в строку?](https://python-all.ru/2.7/faq/programming.html#id30)846847Чтобы преобразовать, например, число 144 в строку '144', используйте встроенный конструктор типа [`str()`](https://python-all.ru/2.7/library/functions.html#str). Если нужны шестнадцатеричное или восьмеричное представление, используйте встроенные функции [`hex()`](https://python-all.ru/2.7/library/functions.html#hex) или [`oct()`](https://python-all.ru/2.7/library/functions.html#oct). Для тонкого форматирования см. раздел [Синтаксис форматных строк](https://python-all.ru/2.7/library/string.html#formatstrings), например `"{:04d}".format(144)` даёт `'0144'` и `"{:.3f}".format(1.0/3.0)` даёт `'0.333'`. В Python 2 оператор деления (/) возвращает целую часть математического результата деления, если аргументы – int или long, но возвращает разумное приближение результата деления, если аргументы – float или complex:848849```python850>>> print('{:.3f}'.format(1/3))8510.000852>>> print('{:.3f}'.format(1.0/3))8530.333854```855856В Python 3 поведение оператора деления по умолчанию (см. [**PEP 238**](https://python-all.ru/2.7/faq/programming.html)) было изменено, но вы можете получить то же поведение в Python 2, если импортируете `division` из [`__future__`](https://python-all.ru/2.7/library/__future__.html#module-__future__):857858```python859>>> from __future__ import division860>>> print('{:.3f}'.format(1/3))8610.333862```863864Вы также можете использовать [оператор %](https://python-all.ru/2.7/library/stdtypes.html#string-formatting) для строк. Подробности см. в справочном руководстве по библиотеке.865866### [Как изменить строку на месте?](https://python-all.ru/2.7/faq/programming.html#id31)867868Так сделать нельзя, потому что строки неизменяемы. Если нужен объект с такой возможностью, попробуйте преобразовать строку в список или используйте модуль array:869870```python871>>> import io872>>> s = "Hello, world"873>>> a = list(s)874>>> print a875['H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd']876>>> a[7:] = list("there!")877>>> ''.join(a)878'Hello, there!'879880>>> import array881>>> a = array.array('c', s)882>>> print a883array('c', 'Hello, world')884>>> a[0] = 'y'; print a885array('c', 'yello, world')886>>> a.tostring()887'yello, world'888```889890### [Как использовать строки для вызова функций/методов?](https://python-all.ru/2.7/faq/programming.html#id32)891892Существует несколько приёмов.893894- Лучший из них – использовать словарь, сопоставляющий строки с функциями. Главное преимущество этого подхода в том, что строки не обязаны совпадать с именами функций. Это также основной способ эмуляции конструкции case:895896  ```python897  def a():898      pass899900  def b():901      pass902903  dispatch = {'go': a, 'stop': b}  # Обратите внимание на отсутствие скобок для функций904905  dispatch[get_input()]()  # Обратите внимание на завершающие скобки для вызова функции906  ```907- Используйте встроенную функцию [`getattr()`](https://python-all.ru/2.7/library/functions.html#getattr):908909  ```python910  import foo911  getattr(foo, 'bar')()912  ```913914  Обратите внимание: [`getattr()`](https://python-all.ru/2.7/library/functions.html#getattr) работает с любыми объектами, включая классы, экземпляры классов, модули и т.д.915916  Это используется в нескольких местах стандартной библиотеки, например:917918  ```python919  class Foo:920      def do_foo(self):921          ...922923      def do_bar(self):924          ...925926  f = getattr(foo_instance, 'do_' + opname)927  f()928  ```929- Используйте [`locals()`](https://python-all.ru/2.7/library/functions.html#locals) или [`eval()`](https://python-all.ru/2.7/library/functions.html#eval) для разрешения имени функции:930931  ```python932  def myFunc():933      print "hello"934935  fname = "myFunc"936937  f = locals()[fname]938  f()939940  f = eval(fname)941  f()942  ```943944  Примечание: использование [`eval()`](https://python-all.ru/2.7/library/functions.html#eval) медленно и опасно. Если у вас нет абсолютного контроля над содержимым строки, кто-то может передать строку, которая приведёт к выполнению произвольной функции.945946### [Существует ли аналог функции chomp() из Perl для удаления завершающих символов новой строки из строк?](https://python-all.ru/2.7/faq/programming.html#id33)947948Начиная с Python 2.2 вы можете использовать `S.rstrip("\r\n")` для удаления всех символов конца строки в конце строки `S` без удаления других завершающих пробелов. Если строка `S` содержит более одной строки и заканчивается несколькими пустыми строками, все символы конца строки для этих пустых строк будут удалены:949950```python951>>> lines = ("line 1 \r\n"952...          "\r\n"953...          "\r\n")954>>> lines.rstrip("\n\r")955'line 1 '956```957958Поскольку такой подход обычно нужен только при чтении текста построчно, `S.rstrip()` в таком виде отлично подходит.959960Для более старых версий Python есть две частичные замены:961962- Если нужно удалить все завершающие пробельные символы, используйте метод строковых объектов `rstrip()`. Он удаляет все завершающие пробельные символы, а не только один символ новой строки.963- В противном случае, если в строке `S` только одна строка, используйте `S.splitlines()[0]`.964965### [Существует ли аналог функций scanf() или sscanf()?](https://python-all.ru/2.7/faq/programming.html#id34)966967Прямого аналога нет.968969Для простого разбора ввода проще всего разбить строку на слова, разделённые пробельными символами, с помощью метода [`split()`](https://python-all.ru/2.7/library/stdtypes.html#str.split) строковых объектов, а затем преобразовать десятичные строки в числа через [`int()`](https://python-all.ru/2.7/library/functions.html#int) или [`float()`](https://python-all.ru/2.7/library/functions.html#float). Функция `split()` поддерживает необязательный параметр «sep», который удобен, если разделителем выступает не пробел.970971Для более сложного разбора ввода регулярные выражения мощнее, чем C-функция `sscanf()`, и лучше подходят для этой задачи.972973### [Что означает ошибка «UnicodeError: ASCII \[decoding,encoding\] error: ordinal not in range(128)»?](https://python-all.ru/2.7/faq/programming.html#id35)974975Эта ошибка означает, что ваша установка Python может обрабатывать только 7-битные строки ASCII. Есть несколько способов исправить или обойти проблему.976977Если ваши программы должны обрабатывать данные в произвольных кодировках, среда, в которой работает приложение, обычно определяет кодировку передаваемых данных. Вам нужно преобразовать входные данные в Unicode, используя эту кодировку. Например, программа, обрабатывающая электронную почту или веб-ввод, обычно находит информацию о кодировке в заголовках Content-Type. Затем это можно использовать для правильного преобразования входных данных в Unicode. Предположим, что строка, на которую ссылается `value`, закодирована в UTF-8:978979```python980value = unicode(value, "utf-8")981```982983вернёт объект Unicode. Если данные неверно закодированы в UTF-8, указанный вызов вызовет исключение [`UnicodeError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.UnicodeError).984985Если вы хотите преобразовывать в Unicode только строки, содержащие не-ASCII данные, можно сначала попробовать преобразовать их, считая их ASCII, а затем создавать объекты Unicode, если это не удалось:986987```python988try:989    x = unicode(value, "ascii")990except UnicodeError:991    value = unicode(value, "utf-8")992else:993    # значение было допустимыми ASCII-данными994    pass995```996997Можно задать кодировку по умолчанию в файле `sitecustomize.py`, который является частью библиотеки Python. Однако это не рекомендуется, так как изменение общепитоновской кодировки по умолчанию может привести к сбоям сторонних модулей расширения.998999Обратите внимание, что в Windows существует кодировка «mbcs», которая использует кодировку, специфичную для текущей локали. Во многих случаях, особенно при работе с COM, она может быть подходящей кодировкой по умолчанию.10001001## [Последовательности (кортежи/списки)](https://python-all.ru/2.7/faq/programming.html#id36)10021003### [Как преобразовывать кортежи и списки друг в друга?](https://python-all.ru/2.7/faq/programming.html#id37)10041005Конструктор типа `tuple(seq)` преобразует любую последовательность (на самом деле любой итерируемый объект) в кортеж с теми же элементами в том же порядке.10061007Например, `tuple([1, 2, 3])` даёт `(1, 2, 3)`, а `tuple('abc')` даёт `('a', 'b', 'c')`. Если аргумент уже является кортежем, копия не создаётся – возвращается тот же объект, поэтому вызов [`tuple()`](https://python-all.ru/2.7/library/functions.html#tuple) обходится дёшево, когда нет уверенности, что объект уже является кортежем.10081009Конструктор типа `list(seq)` преобразует любую последовательность или итерируемый объект в список с теми же элементами в том же порядке. Например, `list((1, 2, 3))` даёт `[1, 2, 3]`, а `list('abc')` даёт `['a', 'b', 'c']`. Если аргумент является списком, создаётся копия, как и в случае `seq[:]`.10101011### [Что такое отрицательный индекс?](https://python-all.ru/2.7/faq/programming.html#id38)10121013Последовательности Python индексируются положительными и отрицательными числами. Для положительных чисел 0 – это первый индекс, 1 – второй и так далее. Для отрицательных индексов -1 – последний индекс, -2 – предпоследний (перед последним) и так далее. Считайте `seq[-n]` тем же, что и `seq[len(seq)-n]`.10141015Использование отрицательных индексов может быть очень удобным. Например, `S[:-1]` – это вся строка, кроме последнего символа, что полезно для удаления завершающего перевода строки.10161017### [Как перебрать последовательность в обратном порядке?](https://python-all.ru/2.7/faq/programming.html#id39)10181019Используйте встроенную функцию [`reversed()`](https://python-all.ru/2.7/library/functions.html#reversed), которая появилась в Python 2.4:10201021```python1022for x in reversed(sequence):1023    ...  # сделать что-то с x ...1024```10251026Это не затронет исходную последовательность, а создаст новую копию с обратным порядком для итерации.10271028В Python 2.3 можно использовать расширенный синтаксис срезов:10291030```python1031for x in sequence[::-1]:1032    ...  # сделать что-то с x ...1033```10341035### [Как удалить дубликаты из списка?](https://python-all.ru/2.7/faq/programming.html#id40)10361037См. Python Cookbook, где подробно рассматриваются многие способы сделать это:10381039> [https://code.activestate.com/recipes/52560/](https://python-all.ru/2.7/faq/programming.html)10401041Если перестановка элементов списка не страшна, отсортируйте его, а затем просмотрите с конца, удаляя дубликаты по ходу:10421043```python1044if mylist:1045    mylist.sort()1046    last = mylist[-1]1047    for i in range(len(mylist)-2, -1, -1):1048        if last == mylist[i]:1049            del mylist[i]1050        else:1051            last = mylist[i]1052```10531054Если все элементы списка могут быть использованы как ключи словаря (то есть они все хешируемы), это часто быстрее10551056```python1057d = {}1058for x in mylist:1059    d[x] = 11060mylist = list(d.keys())1061```10621063В Python 2.5 и новее вместо этого можно сделать следующее:10641065```python1066mylist = list(set(mylist))1067```10681069Это преобразует список во множество, удаляя дубликаты, а затем обратно в список.10701071### [Как создать массив в Python?](https://python-all.ru/2.7/faq/programming.html#id41)10721073Используйте список:10741075```python1076["this", 1, "is", "an", "array"]1077```10781079По временно́й сложности списки эквивалентны массивам C или Pascal; основное отличие в том, что список Python может содержать объекты разных типов.10801081Модуль `array` также предоставляет методы для создания массивов фиксированных типов с компактным представлением, но они медленнее при индексации, чем списки. Также обратите внимание, что расширения Numeric и другие определяют структуры, подобные массивам, с различными характеристиками.10821083Чтобы получить связные списки в стиле Lisp, можно эмулировать ячейки cons с помощью кортежей:10841085```python1086lisp_list = ("like",  ("this",  ("example", None) ) )1087```10881089Если нужна изменяемость, можно использовать списки вместо кортежей. Здесь аналог lisp car – это `lisp_list[0]`, а аналог cdr – `lisp_list[1]`. Делайте так, только если уверены, что это действительно необходимо, потому что обычно это намного медленнее, чем использование списков Python.10901091### [Как создать многомерный список?](https://python-all.ru/2.7/faq/programming.html#id42)10921093Вероятно, вы пытались создать многомерный массив так:10941095```python1096>>> A = [[None] * 2] * 31097```10981099Если вывести его, выглядит правильно:11001101```python1102>>> A1103[[None, None], [None, None], [None, None]]1104```11051106Но когда вы присваиваете значение, оно появляется в нескольких местах:11071108```python1109>>> A[0][0] = 51110>>> A1111[[5, None], [5, None], [5, None]]1112```11131114Причина в том, что размножение списка с помощью `*` не создаёт копии, а только ссылки на существующие объекты. `*3` создаёт список из 3 ссылок на один и тот же список длины два. Изменения в одной строке отразятся во всех строках, что почти наверняка не то, что нужно.11151116Рекомендуемый подход – сначала создать список нужной длины, а затем заполнить каждый элемент заново созданным списком:11171118```python1119A = [None] * 31120for i in range(3):1121    A[i] = [None] * 21122```11231124Это порождает список, содержащий 3 разных списка длины два. Также можно использовать списковое включение:11251126```python1127w, h = 2, 31128A = [[None] * w for i in range(h)]1129```11301131Или можно воспользоваться расширением, предоставляющим тип данных «матрица»; наиболее известен [NumPy](https://python-all.ru/2.7/faq/programming.html).11321133### [Как применить метод к последовательности объектов?](https://python-all.ru/2.7/faq/programming.html#id43)11341135Используйте списковое включение:11361137```python1138result = [obj.method() for obj in mylist]1139```11401141В более общем случае можно попробовать следующую функцию:11421143```python1144def method_map(objects, method, arguments):1145    """method_map([a,b], "meth", (1,2)) даёт [a.meth(1,2), b.meth(1,2)]"""1146    nobjects = len(objects)1147    methods = map(getattr, objects, [method]*nobjects)1148    return map(apply, methods, [arguments]*nobjects)1149```11501151### [Почему a\_tuple\[i\] += \['item'\] вызывает исключение, хотя сложение работает?](https://python-all.ru/2.7/faq/programming.html#id44)11521153Это связано с тем, что операторы расширенного присваивания являются *операторами присваивания*, а также с различием между изменяемыми и неизменяемыми объектами в Python.11541155Это обсуждение в целом применимо, когда операторы расширенного присваивания применяются к элементам кортежа, указывающим на изменяемые объекты, но в качестве примера мы используем `list` и `+=`.11561157Если написать:11581159```python1160>>> a_tuple = (1, 2)1161>>> a_tuple[0] += 11162Traceback (most recent call last):1163   ...1164TypeError: 'tuple' object does not support item assignment1165```11661167Причина исключения сразу становится ясна: `1` добавляется к объекту, на который указывает `a_tuple[0]` (`1`), в результате получается объект `2`, но когда мы пытаемся присвоить результат вычисления `2` элементу `0` кортежа, возникает ошибка, потому что нельзя изменить, на что указывает элемент кортежа.11681169На самом деле то, что делает этот расширенный оператор присваивания, примерно таково:11701171```python1172>>> result = a_tuple[0] + 11173>>> a_tuple[0] = result1174Traceback (most recent call last):1175  ...1176TypeError: 'tuple' object does not support item assignment1177```11781179Ошибку вызывает именно часть присваивания операции, поскольку кортеж неизменяем.11801181Если написать что-то вроде:11821183```python1184>>> a_tuple = (['foo'], 'bar')1185>>> a_tuple[0] += ['item']1186Traceback (most recent call last):1187  ...1188TypeError: 'tuple' object does not support item assignment1189```11901191Исключение несколько более неожиданно, и еще более удивительно то, что, несмотря на ошибку, append сработал:11921193```python1194>>> a_tuple[0]1195['foo', 'item']1196```11971198Чтобы понять, почему это происходит, нужно знать: (а) если объект реализует магический метод `__iadd__`, он вызывается, когда выполняется расширенное присваивание `+=`, и его возвращаемое значение используется в операторе присваивания; и (б) для списков `__iadd__` эквивалентно вызову `extend` для списка и возврату этого списка. Поэтому мы говорим, что для списков `+=` – это «сокращение» для `list.extend`:11991200```python1201>>> a_list = []1202>>> a_list += [1]1203>>> a_list1204[1]1205```12061207Это эквивалентно:12081209```python1210>>> result = a_list.__iadd__([1])1211>>> a_list = result1212```12131214Объект, на который указывает a\_list, был изменён, и указатель на изменённый объект присваивается обратно `a_list`. Конечный результат присваивания – холостая операция (no-op), поскольку это указатель на тот же объект, на который `a_list` указывал ранее, но само присваивание всё равно происходит.12151216Таким образом, в нашем примере с кортежем происходит то же самое, что и в:12171218```python1219>>> result = a_tuple[0].__iadd__(['item'])1220>>> a_tuple[0] = result1221Traceback (most recent call last):1222  ...1223TypeError: 'tuple' object does not support item assignment1224```12251226`__iadd__` выполняется успешно, и список расширяется, но, хотя `result` указывает на тот же объект, на который уже указывает `a_tuple[0]`, финальное присваивание всё равно вызывает ошибку, поскольку кортежи неизменяемы.12271228## [Словари](https://python-all.ru/2.7/faq/programming.html#id45)12291230### [Как сделать так, чтобы ключи словаря отображались в постоянном порядке?](https://python-all.ru/2.7/faq/programming.html#id46)12311232Невозможно. Словари хранят ключи в непредсказуемом порядке, поэтому порядок отображения элементов словаря будет таким же непредсказуемым.12331234Это может раздражать, если вы хотите сохранить печатную версию в файл, внести некоторые изменения и затем сравнить её с другим распечатанным словарём. В этом случае используйте модуль `pprint` для красивой печати словаря; элементы будут представлены в порядке, отсортированном по ключу.12351236Более сложное решение – создать подкласс `dict`, чтобы получить класс `SortedDict`, который выводит себя в предсказуемом порядке. Вот одна простенькая реализация такого класса:12371238```python1239class SortedDict(dict):1240    def __repr__(self):1241        keys = sorted(self.keys())1242        result = ("{!r}: {!r}".format(k, self[k]) for k in keys)1243        return "{{{}}}".format(", ".join(result))12441245    __str__ = __repr__1246```12471248Это будет работать для многих распространённых ситуаций, которые могут встретиться, хотя это далеко не идеальное решение. Самый большой недостаток: если некоторые значения в словаре сами являются словарями, их значения не будут представлены в каком-либо определённом порядке.12491250### [Я хочу выполнить сложную сортировку: можно ли сделать преобразование Шварца в Python?](https://python-all.ru/2.7/faq/programming.html#id47)12511252Эта техника, приписываемая Рэндалу Шварцу из сообщества Perl, сортирует элементы списка по метрике, которая сопоставляет каждый элемент с его «значением сортировки». В Python используйте аргумент `key` для функции `sort()`:12531254```python1255Isorted = L[:]1256Isorted.sort(key=lambda s: int(s[10:15]))1257```12581259### [Как отсортировать один список по значениям из другого списка?](https://python-all.ru/2.7/faq/programming.html#id48)12601261Объедините их в единый список кортежей, отсортируйте полученный список, а затем выберите нужный элемент.12621263```python1264>>> list1 = ["what", "I'm", "sorting", "by"]1265>>> list2 = ["something", "else", "to", "sort"]1266>>> pairs = zip(list1, list2)1267>>> pairs1268[('what', 'something'), ("I'm", 'else'), ('sorting', 'to'), ('by', 'sort')]1269>>> pairs.sort()1270>>> result = [ x[1] for x in pairs ]1271>>> result1272['else', 'sort', 'to', 'something']1273```12741275Альтернатива для последнего шага:12761277```python1278>>> result = []1279>>> for p in pairs: result.append(p[1])1280```12811282Если вам это кажется более читаемым, вы можете предпочесть использовать это вместо конечного спискового включения. Однако для длинных списков это почти в два раза медленнее. Почему? Во-первых, операция `append()` должна перераспределять память, и хотя она использует некоторые трюки, чтобы избегать этого каждый раз, иногда ей всё же приходится это делать, что стоит довольно дорого. Во-вторых, выражение «result.append» требует дополнительного поиска атрибута, и в-третьих, скорость снижается из-за необходимости совершать все эти вызовы функций.12831284## [Объекты](https://python-all.ru/2.7/faq/programming.html#id49)12851286### [Что такое класс?](https://python-all.ru/2.7/faq/programming.html#id50)12871288Класс – это конкретный тип объекта, создаваемый при выполнении инструкции class. Объекты классов используются как шаблоны для создания объектов-экземпляров, которые содержат как данные (атрибуты), так и код (методы), характерные для данного типа данных.12891290Класс может быть основан на одном или нескольких других классах, называемых его базовыми классами. Он наследует атрибуты и методы своих базовых классов. Это позволяет последовательно уточнять объектную модель с помощью наследования. Например, можно иметь общий класс `Mailbox`, предоставляющий базовые методы доступа к почтовому ящику, и подклассы `MboxMailbox`, `MaildirMailbox`, `OutlookMailbox`, обрабатывающие различные форматы почтовых ящиков.12911292### [Что такое метод?](https://python-all.ru/2.7/faq/programming.html#id51)12931294Метод – это функция некоторого объекта `x`, которая обычно вызывается как `x.name(arguments...)`. Методы определяются как функции внутри определения класса:12951296```python1297class C:1298    def meth(self, arg):1299        return arg * 2 + self.attribute1300```13011302### [Что такое self?](https://python-all.ru/2.7/faq/programming.html#id52)13031304Self – это просто условное имя для первого аргумента метода. Метод, определённый как `meth(self, a, b, c)`, должен вызываться как `x.meth(a, b, c)` для некоторого экземпляра `x` класса, в котором находится определение; вызванный метод будет считать, что его вызвали как `meth(x, a, b, c)`.13051306См. также [Почему self должно явно использоваться в определениях и вызовах методов?](https://python-all.ru/2.7/faq/design.html#why-self).13071308### [Как проверить, является ли объект экземпляром данного класса или его подкласса?](https://python-all.ru/2.7/faq/programming.html#id53)13091310Используйте встроенную функцию `isinstance(obj, cls)`. Можно проверить, является ли объект экземпляром любого из нескольких классов, передав кортеж вместо одного класса, например `isinstance(obj, (class1, class2, ...))`, а также проверить, является ли объект одним из встроенных типов Python, например `isinstance(obj, str)` или `isinstance(obj, (int, long, float, complex))`.13111312Обратите внимание, что большинство программ не используют [`isinstance()`](https://python-all.ru/2.7/library/functions.html#isinstance) для пользовательских классов очень часто. Если вы разрабатываете классы сами, более правильным объектно-ориентированным стилем будет определение методов в классах, инкапсулирующих определённое поведение, вместо проверки класса объекта и выполнения разных действий в зависимости от того, какой это класс. Например, если есть функция, которая делает что-то:13131314```python1315def search(obj):1316    if isinstance(obj, Mailbox):1317        ...  # код для поиска почтового ящика1318    elif isinstance(obj, Document):1319        ...  # код для поиска документа1320    elif ...1321```13221323Лучше определить метод `search()` во всех классах и просто вызывать его:13241325```python1326class Mailbox:1327    def search(self):1328        ...  # код для поиска почтового ящика13291330class Document:1331    def search(self):1332        ...  # код для поиска документа13331334obj.search()1335```13361337### [Что такое делегирование?](https://python-all.ru/2.7/faq/programming.html#id54)13381339Делегирование – это объектно-ориентированная техника (также называемая шаблоном проектирования). Допустим, у вас есть объект `x` и нужно изменить поведение только одного из его методов. Можно создать новый класс, который предоставляет новую реализацию интересующего метода и делегирует все остальные методы соответствующему методу объекта `x`.13401341Программисты на Python могут легко реализовать делегирование. Например, следующий класс реализует класс, который ведёт себя как файл, но преобразует все записываемые данные в верхний регистр:13421343```python1344class UpperOut:13451346    def __init__(self, outfile):1347        self._outfile = outfile13481349    def write(self, s):1350        self._outfile.write(s.upper())13511352    def __getattr__(self, name):1353        return getattr(self._outfile, name)1354```13551356Here the `UpperOut` class redefines the `write()` method to convert the argument string to uppercase before calling the underlying `self.__outfile.write()` method. All other methods are delegated to the underlying `self.__outfile` object. The delegation is accomplished via the `__getattr__` method; consult [the language reference](https://python-all.ru/2.7/reference/datamodel.html#attribute-access) for more information about controlling attribute access.13571358Обратите внимание, что в более общих случаях делегирование может усложниться. Если атрибуты нужно не только получать, но и устанавливать, класс должен также определить метод [`__setattr__()`](https://python-all.ru/2.7/reference/datamodel.html#object.__setattr__), и делать это нужно аккуратно. Базовая реализация [`__setattr__()`](https://python-all.ru/2.7/reference/datamodel.html#object.__setattr__) примерно эквивалентна следующему:13591360```python1361class X:1362    ...1363    def __setattr__(self, name, value):1364        self.__dict__[name] = value1365    ...1366```13671368Большинство реализаций [`__setattr__()`](https://python-all.ru/2.7/reference/datamodel.html#object.__setattr__) должны изменять `self.__dict__` для хранения локального состояния для self, чтобы избежать бесконечной рекурсии.13691370### [Как вызвать метод, определённый в базовом классе, из производного класса, который его переопределяет?](https://python-all.ru/2.7/faq/programming.html#id55)13711372Если вы используете классы нового стиля, используйте встроенную функцию [`super()`](https://python-all.ru/2.7/library/functions.html#super):13731374```python1375class Derived(Base):1376    def meth(self):1377        super(Derived, self).meth()1378```13791380Если вы используете классические классы: для определения класса, такого как `class Derived(Base): ...`, вы можете вызвать метод `meth()`, определённый в `Base` (или одном из базовых классов `Base`), как `Base.meth(self, arguments...)`. Здесь `Base.meth` – это непривязанный метод, поэтому вам нужно указать аргумент `self`.13811382### [Как организовать код, чтобы было проще изменить базовый класс?](https://python-all.ru/2.7/faq/programming.html#id56)13831384Можно определить псевдоним для базового класса, присвоить ему реальный базовый класс до определения вашего класса и использовать псевдоним во всём классе. Тогда всё, что нужно изменить – это значение, присвоенное псевдониму. Кстати, этот трюк также удобен, если вы хотите динамически (например, в зависимости от доступности ресурсов) выбирать, какой базовый класс использовать. Пример:13851386```python1387BaseAlias = <real base class>13881389class Derived(BaseAlias):1390    def meth(self):1391        BaseAlias.meth(self)1392        ...1393```13941395### [Как создать статические данные класса и статические методы класса?](https://python-all.ru/2.7/faq/programming.html#id57)13961397В Python поддерживаются как статические данные, так и статические методы (в смысле C++ или Java).13981399Для статических данных просто определите атрибут класса. Чтобы присвоить атрибуту новое значение, необходимо явно указать имя класса в присваивании:14001401```python1402class C:1403    count = 0   # количество вызовов C.__init__14041405    def __init__(self):1406        C.count = C.count + 114071408    def getcount(self):1409        return C.count  # или вернуть self.count1410```14111412`c.count` также ссылается на `C.count` для любого `c`, для которого `isinstance(c, C)` истинно, если только оно не переопределено самим `c` или каким-либо классом на пути поиска базового класса от `c.__class__` до `C`.14131414Внимание: внутри метода C присваивание вида `self.count = 42` создаёт новый и не связанный экземпляр с именем «count» в собственном словаре `self`. Повторное связывание имени статических данных класса всегда должно указывать класс, как внутри метода, так и вне его:14151416```python1417C.count = 3141418```14191420Статические методы возможны начиная с Python 2.2:14211422```python1423class C:1424    def static(arg1, arg2, arg3):1425        # Нет параметра 'self'!1426        ...1427    static = staticmethod(static)1428```14291430С помощью декораторов Python 2.4 это также можно записать как14311432```python1433class C:1434    @staticmethod1435    def static(arg1, arg2, arg3):1436        # Нет параметра 'self'!1437        ...1438```14391440Однако гораздо более прямолинейный способ получить эффект статического метода – это простая функция уровня модуля:14411442```python1443def getcount():1444    return C.count1445```14461447Если код организован так, что на каждый модуль определён один класс (или тесно связанная иерархия классов), это обеспечивает нужную инкапсуляцию.14481449### [Как перегрузить конструкторы (или методы) в Python?](https://python-all.ru/2.7/faq/programming.html#id58)14501451Этот ответ на самом деле применим ко всем методам, но вопрос обычно возникает в первую очередь в контексте конструкторов.14521453В C++ вы бы написали14541455```c1456class C {1457    C() { cout << "No arguments\n"; }1458    C(int i) { cout << "Argument is " << i << "\n"; }1459}1460```14611462В Python нужно написать один конструктор, который обрабатывает все случаи с помощью аргументов по умолчанию. Например:14631464```python1465class C:1466    def __init__(self, i=None):1467        if i is None:1468            print "No arguments"1469        else:1470            print "Argument is", i1471```14721473Это не полностью эквивалентно, но на практике достаточно близко.14741475Можно также попробовать список аргументов переменной длины, например14761477```python1478def __init__(self, *args):1479    ...1480```14811482Тот же подход работает для всех определений методов.14831484### [Я пытаюсь использовать \_\_spam и получаю ошибку про \_SomeClassName\_\_spam.](https://python-all.ru/2.7/faq/programming.html#id59)14851486Имена переменных с двойным подчёркиванием в начале «искажаются» – это простой, но эффективный способ определения приватных переменных класса. Любой идентификатор вида `__spam` (не менее двух начальных подчёркиваний и не более одного конечного) текстуально заменяется на `_classname__spam`, где `classname` – это имя текущего класса без начальных подчёркиваний.14871488Это не гарантирует приватности: внешний пользователь все еще может намеренно получить доступ к атрибуту «\_classname\_\_spam», а приватные значения видны в `__dict__` объекта. Многие программисты на Python вообще не утруждают себя использованием имен приватных переменных.14891490### [Мой класс определяет \_\_del\_\_, но он не вызывается, когда я удаляю объект.](https://python-all.ru/2.7/faq/programming.html#id60)14911492Для этого есть несколько возможных причин.14931494Оператор del не обязательно вызывает [`__del__()`](https://python-all.ru/2.7/reference/datamodel.html#object.__del__) – он просто уменьшает счётчик ссылок объекта, и если он достигает нуля, вызывается [`__del__()`](https://python-all.ru/2.7/reference/datamodel.html#object.__del__).14951496Если ваши структуры данных содержат циклические ссылки (например, дерево, где каждый потомок имеет ссылку на родителя, а каждый родитель – список потомков), счётчики ссылок никогда не обнулятся. Время от времени Python запускает алгоритм для обнаружения таких циклов, но сборщик мусора может запуститься спустя некоторое время после того, как последняя ссылка на вашу структуру данных исчезнет, так что метод [`__del__()`](https://python-all.ru/2.7/reference/datamodel.html#object.__del__) может быть вызван в неудобный и случайный момент. Это неудобно, если вы пытаетесь воспроизвести проблему. Хуже того, порядок вызова методов [`__del__()`](https://python-all.ru/2.7/reference/datamodel.html#object.__del__) объектов произволен. Можно запустить [`gc.collect()`](https://python-all.ru/2.7/library/gc.html#gc.collect) для принудительной сборки, но существуют *патологические* случаи, когда объекты никогда не будут собраны.14971498Несмотря на сборщик циклических ссылок, всё равно рекомендуется определять явный метод `close()` для объектов, который будет вызываться, когда объект больше не нужен. Метод `close()` может затем удалять атрибуты, ссылающиеся на подобъекты. Не вызывайте [`__del__()`](https://python-all.ru/2.7/reference/datamodel.html#object.__del__) напрямую – [`__del__()`](https://python-all.ru/2.7/reference/datamodel.html#object.__del__) должен вызывать `close()` и `close()` должен гарантировать, что он может быть вызван более одного раза для одного и того же объекта.14991500Другой способ избежать циклических ссылок – использовать модуль [`weakref`](https://python-all.ru/2.7/library/weakref.html#module-weakref), который позволяет указывать на объекты без увеличения их счётчика ссылок. Например, структуры данных деревьев должны использовать слабые ссылки для ссылок на родительские и дочерние элементы (если они нужны!).15011502Если объект когда-либо был локальной переменной в функции, которая перехватила выражение в предложении except, велика вероятность, что ссылка на объект всё ещё существует в стековом кадре этой функции, как содержится в трассировке стека. Обычно вызов [`sys.exc_clear()`](https://python-all.ru/2.7/library/sys.html#sys.exc_clear) позаботится об этом, очистив последнюю записанную исключительную ситуацию.15031504Наконец, если метод [`__del__()`](https://python-all.ru/2.7/reference/datamodel.html#object.__del__) вызывает исключение, предупреждение выводится в [`sys.stderr`](https://python-all.ru/2.7/library/sys.html#sys.stderr).15051506### [Как получить список всех экземпляров данного класса?](https://python-all.ru/2.7/faq/programming.html#id61)15071508Python не отслеживает все экземпляры класса (или встроенного типа). Можно запрограммировать конструктор класса так, чтобы он отслеживал все экземпляры, сохраняя список слабых ссылок на каждый экземпляр.15091510### [Почему результат `id()` кажется неуникальным?](https://python-all.ru/2.7/faq/programming.html#id62)15111512Встроенная функция [`id()`](https://python-all.ru/2.7/library/functions.html#id) возвращает целое число, которое гарантированно уникально в течение времени жизни объекта. Поскольку в CPython это адрес памяти объекта, часто бывает, что после удаления объекта из памяти следующий свежесозданный объект выделяется по тому же адресу. Это показано на следующем примере:15131514```python1515>>> id(1000)1516139012721517>>> id(2000)1518139012721519```15201521Два идентификатора принадлежат разным целочисленным объектам, которые создаются до и сразу же удаляются после выполнения вызова `id()`. Чтобы убедиться, что объекты, чей id нужно проверить, всё ещё живы, создайте ещё одну ссылку на объект:15221523```python1524>>> a = 1000; b = 20001525>>> id(a)1526139012721527>>> id(b)1528138912961529```15301531## [Модули](https://python-all.ru/2.7/faq/programming.html#id63)15321533### [Как создать .pyc-файл?](https://python-all.ru/2.7/faq/programming.html#id64)15341535При первом импорте модуля (или когда исходный код новее текущего скомпилированного файла) в том же каталоге, что и файл `.py`, должен быть создан файл `.pyc`, содержащий скомпилированный код.15361537Одна из причин, по которой файл `.pyc` может не создаваться, – проблемы с правами доступа к каталогу. Это может случиться, например, если вы разрабатываете как один пользователь, а запускаете как другой, например, при тестировании с веб-сервером. Создание файла .pyc происходит автоматически при импорте модуля, если у Python есть возможность (права, свободное место и т. д.) записать скомпилированный модуль обратно в каталог.15381539Запуск Python на скрипте верхнего уровня не считается импортом, и файл `.pyc` создан не будет. Например, если у вас есть модуль верхнего уровня `foo.py`, который импортирует другой модуль `xyz.py`, то при запуске `foo` будет создан `xyz.pyc`, так как `xyz` импортируется, но файл `foo.pyc` не будет создан, поскольку `foo.py` не импортируется.15401541Если вам нужно создать `foo.pyc` – то есть создать файл `.pyc` для модуля, который не импортируется, – вы можете использовать модули [`py_compile`](https://python-all.ru/2.7/library/py_compile.html#module-py_compile) и [`compileall`](https://python-all.ru/2.7/library/compileall.html#module-compileall).15421543Модуль [`py_compile`](https://python-all.ru/2.7/library/py_compile.html#module-py_compile) может вручную скомпилировать любой модуль. Один из способов – интерактивно использовать функцию `compile()` в этом модуле:15441545```python1546>>> import py_compile1547>>> py_compile.compile('foo.py')                 1548```15491550Это запишет `.pyc` в то же место, что и `foo.py` (или вы можете переопределить это с помощью необязательного параметра `cfile`).15511552Также можно автоматически скомпилировать все файлы в каталоге или каталогах с помощью модуля [`compileall`](https://python-all.ru/2.7/library/compileall.html#module-compileall). Для этого из командной оболочки выполните `compileall.py` и укажите путь к каталогу, содержащему файлы Python для компиляции:15531554```python1555python -m compileall .1556```15571558### [Как узнать имя текущего модуля?](https://python-all.ru/2.7/faq/programming.html#id65)15591560Модуль может узнать своё собственное имя, обратившись к предопределённой глобальной переменной `__name__`. Если она равна `'__main__'`, программа выполняется как скрипт. Многие модули, которые обычно используются через импорт, также предоставляют интерфейс командной строки или самопроверку и выполняют этот код только после проверки `__name__`:15611562```python1563def main():1564    print 'Running test...'1565    ...15661567if __name__ == '__main__':1568    main()1569```15701571### [Как сделать модули, которые импортируют друг друга?](https://python-all.ru/2.7/faq/programming.html#id66)15721573Предположим, у вас есть следующие модули:15741575foo.py:15761577```python1578from bar import bar_var1579foo_var = 11580```15811582bar.py:15831584```python1585from foo import foo_var1586bar_var = 21587```15881589Проблема в том, что интерпретатор выполнит следующие шаги:15901591- main импортирует foo1592- Создаются пустые глобальные переменные для foo1593- foo компилируется и начинает выполняться1594- foo импортирует bar1595- Создаются пустые глобальные переменные для bar1596- bar компилируется и начинает выполняться1597- bar импортирует foo (это пустая операция, так как модуль с именем foo уже существует)1598- bar.foo\_var = foo.foo\_var15991600Последний шаг завершается неудачей, потому что Python ещё не закончил интерпретацию `foo`, и словарь глобальных символов для `foo` всё ещё пуст.16011602То же самое происходит при использовании `import foo` и последующей попытке обратиться к `foo.foo_var` в глобальном коде.16031604Существует (как минимум) три возможных обходных решения этой проблемы.16051606Гвидо ван Россум рекомендует избегать любых использований `from <module> import ...` и размещать весь код внутри функций. Инициализация глобальных переменных и переменных класса должна использовать только константы или встроенные функции. Это означает, что всё из импортированного модуля должно ссылаться как `<module>.<name>`.16071608Джим Роскинд предлагает выполнять шаги в следующем порядке в каждом модуле:16091610- экспорт (глобальные переменные, функции и классы, которым не нужны импортированные базовые классы)1611- инструкции `import`1612- активный код (включая глобальные переменные, инициализируемые из импортированных значений).16131614ван Россуму такой подход не очень нравится, потому что импорты оказываются в странном месте, но это работает.16151616Маттиас Урлихс рекомендует перестроить код так, чтобы рекурсивный импорт вообще не требовался.16171618Эти решения не являются взаимоисключающими.16191620### [\_\_import\_\_(‘x.y.z’) возвращает \<module ‘x’\>; как получить z?](https://python-all.ru/2.7/faq/programming.html#id67)16211622Рассмотрите возможность использования удобной функции [`import_module()`](https://python-all.ru/2.7/library/importlib.html#importlib.import_module) из [`importlib`](https://python-all.ru/2.7/library/importlib.html#module-importlib) вместо этого.16231624```python1625z = importlib.import_module('x.y.z')1626```16271628### [Когда я редактирую импортированный модуль и повторно импортирую его, изменения не отображаются. Почему это происходит?](https://python-all.ru/2.7/faq/programming.html#id68)16291630Из соображений эффективности и согласованности Python читает файл модуля только при первом импорте модуля. Если бы это было не так, в программе, состоящей из многих модулей, каждый из которых импортирует один и тот же базовый модуль, базовый модуль разбирался бы и переразбирался многократно. Чтобы принудительно перечитать изменённый модуль, сделайте следующее:16311632```python1633import modname1634reload(modname)1635```16361637Предупреждение: этот метод не является абсолютно надёжным. В частности, модули, содержащие операторы типа16381639```python1640from modname import some_objects1641```16421643будут продолжать работать со старой версией импортированных объектов. Если модуль содержит определения классов, существующие экземпляры классов *не* будут обновлены для использования нового определения класса. Это может привести к следующему парадоксальному поведению:16441645```python1646>>> import cls1647>>> c = cls.C()                # Создать экземпляр C1648>>> reload(cls)1649<module 'cls' from 'cls.pyc'>1650>>> isinstance(c, cls.C)       # isinstance ложно?!?1651False1652```16531654Суть проблемы становится ясной, если вывести объекты классов:16551656```python1657>>> c.__class__1658<class cls.C at 0x7352a0>1659>>> cls.C1660<class cls.C at 0x4198d0>1661```1662