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

programming.md

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

1> **Источник:** https://python-all.ru/3.3/faq/programming.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# [ЧЗВ по программированию](https://python-all.ru/3.3/faq/programming.html#id1)89Содержание1011- [Вопросы по программированию](https://python-all.ru/3.3/faq/programming.html#programming-faq)1213  - [Общие вопросы](https://python-all.ru/3.3/faq/programming.html#general-questions)1415    - [Существует ли отладчик на уровне исходного кода с точками останова, пошаговым выполнением и т. д.?](https://python-all.ru/3.3/faq/programming.html#is-there-a-source-code-level-debugger-with-breakpoints-single-stepping-etc)16    - [Существует ли инструмент для поиска ошибок или выполнения статического анализа?](https://python-all.ru/3.3/faq/programming.html#is-there-a-tool-to-help-find-bugs-or-perform-static-analysis)17    - [Как создать автономный исполняемый файл из скрипта Python?](https://python-all.ru/3.3/faq/programming.html#how-can-i-create-a-stand-alone-binary-from-a-python-script)18    - [Существуют ли стандарты кодирования или руководство по стилю для программ на Python?](https://python-all.ru/3.3/faq/programming.html#are-there-coding-standards-or-a-style-guide-for-python-programs)19  - [Ядро языка](https://python-all.ru/3.3/faq/programming.html#core-language)2021    - [Почему возникает UnboundLocalError, если переменная имеет значение?](https://python-all.ru/3.3/faq/programming.html#why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value)22    - [Каковы правила для локальных и глобальных переменных в Python?](https://python-all.ru/3.3/faq/programming.html#what-are-the-rules-for-local-and-global-variables-in-python)23    - [Почему лямбда-функции, определённые в цикле с разными значениями, возвращают один и тот же результат?](https://python-all.ru/3.3/faq/programming.html#why-do-lambdas-defined-in-a-loop-with-different-values-all-return-the-same-result)24    - [Как разделять глобальные переменные между модулями?](https://python-all.ru/3.3/faq/programming.html#how-do-i-share-global-variables-across-modules)25    - [Каковы «лучшие практики» использования import в модуле?](https://python-all.ru/3.3/faq/programming.html#what-are-the-best-practices-for-using-import-in-a-module)26    - [Как передать необязательные или именованные параметры из одной функции в другую?](https://python-all.ru/3.3/faq/programming.html#how-can-i-pass-optional-or-keyword-parameters-from-one-function-to-another)27    - [В чём разница между аргументами и параметрами?](https://python-all.ru/3.3/faq/programming.html#what-is-the-difference-between-arguments-and-parameters)28    - [Как написать функцию с выходными параметрами (передача по ссылке)?](https://python-all.ru/3.3/faq/programming.html#how-do-i-write-a-function-with-output-parameters-call-by-reference)29    - [Как создать функцию высшего порядка в Python?](https://python-all.ru/3.3/faq/programming.html#how-do-you-make-a-higher-order-function-in-python)30    - [Как скопировать объект в Python?](https://python-all.ru/3.3/faq/programming.html#how-do-i-copy-an-object-in-python)31    - [Как найти методы или атрибуты объекта?](https://python-all.ru/3.3/faq/programming.html#how-can-i-find-the-methods-or-attributes-of-an-object)32    - [Как моему коду узнать имя объекта?](https://python-all.ru/3.3/faq/programming.html#how-can-my-code-discover-the-name-of-an-object)33    - [Что не так с приоритетом оператора запятой?](https://python-all.ru/3.3/faq/programming.html#what-s-up-with-the-comma-operator-s-precedence)34    - [Существует ли эквивалент тернарного оператора ”?:” из C?](https://python-all.ru/3.3/faq/programming.html#is-there-an-equivalent-of-c-s-ternary-operator)35    - [Можно ли писать запутанные однострочники на Python?](https://python-all.ru/3.3/faq/programming.html#is-it-possible-to-write-obfuscated-one-liners-in-python)36  - [Числа и строки](https://python-all.ru/3.3/faq/programming.html#numbers-and-strings)3738    - [Как указать шестнадцатеричные и восьмеричные целые числа?](https://python-all.ru/3.3/faq/programming.html#how-do-i-specify-hexadecimal-and-octal-integers)39    - [Почему -22 // 10 возвращает -3?](https://python-all.ru/3.3/faq/programming.html#why-does-22-10-return-3)40    - [Как преобразовать строку в число?](https://python-all.ru/3.3/faq/programming.html#how-do-i-convert-a-string-to-a-number)41    - [Как преобразовать число в строку?](https://python-all.ru/3.3/faq/programming.html#how-do-i-convert-a-number-to-a-string)42    - [Как изменить строку на месте?](https://python-all.ru/3.3/faq/programming.html#how-do-i-modify-a-string-in-place)43    - [Как с помощью строк вызывать функции и методы?](https://python-all.ru/3.3/faq/programming.html#how-do-i-use-strings-to-call-functions-methods)44    - [Существует ли аналог функции chomp() из Perl для удаления завершающих символов новой строки из строк?](https://python-all.ru/3.3/faq/programming.html#is-there-an-equivalent-to-perl-s-chomp-for-removing-trailing-newlines-from-strings)45    - [Существует ли аналог функций scanf() или sscanf()?](https://python-all.ru/3.3/faq/programming.html#is-there-a-scanf-or-sscanf-equivalent)46    - [Что означает ошибка UnicodeDecodeError или UnicodeEncodeError?](https://python-all.ru/3.3/faq/programming.html#what-does-unicodedecodeerror-or-unicodeencodeerror-error-mean)47  - [Производительность](https://python-all.ru/3.3/faq/programming.html#performance)4849    - [Моя программа слишком медленная. Как её ускорить?](https://python-all.ru/3.3/faq/programming.html#my-program-is-too-slow-how-do-i-speed-it-up)50    - [Какой способ конкатенации множества строк самый эффективный?](https://python-all.ru/3.3/faq/programming.html#what-is-the-most-efficient-way-to-concatenate-many-strings-together)51  - [Последовательности (кортежи/списки)](https://python-all.ru/3.3/faq/programming.html#sequences-tuples-lists)5253    - [Как преобразовывать кортежи в списки и обратно?](https://python-all.ru/3.3/faq/programming.html#how-do-i-convert-between-tuples-and-lists)54    - [Что такое отрицательный индекс?](https://python-all.ru/3.3/faq/programming.html#what-s-a-negative-index)55    - [Как перебрать последовательность в обратном порядке?](https://python-all.ru/3.3/faq/programming.html#how-do-i-iterate-over-a-sequence-in-reverse-order)56    - [Как удалить дубликаты из списка?](https://python-all.ru/3.3/faq/programming.html#how-do-you-remove-duplicates-from-a-list)57    - [Как создать массив в Python?](https://python-all.ru/3.3/faq/programming.html#how-do-you-make-an-array-in-python)58    - [Как создать многомерный список?](https://python-all.ru/3.3/faq/programming.html#how-do-i-create-a-multidimensional-list)59    - [Как применить метод к последовательности объектов?](https://python-all.ru/3.3/faq/programming.html#how-do-i-apply-a-method-to-a-sequence-of-objects)60    - [Почему a\_tuple\[i\] += \[‘item’\] вызывает исключение, хотя само сложение работает?](https://python-all.ru/3.3/faq/programming.html#why-does-a-tuple-i-item-raise-an-exception-when-the-addition-works)61  - [Словари](https://python-all.ru/3.3/faq/programming.html#dictionaries)6263    - [Как сделать, чтобы словарь хранил и выводил ключи в фиксированном порядке?](https://python-all.ru/3.3/faq/programming.html#how-can-i-get-a-dictionary-to-store-and-display-its-keys-in-a-consistent-order)64    - [Я хочу выполнить сложную сортировку: можно ли в Python реализовать преобразование Шварца?](https://python-all.ru/3.3/faq/programming.html#i-want-to-do-a-complicated-sort-can-you-do-a-schwartzian-transform-in-python)65    - [Как отсортировать один список по значениям из другого списка?](https://python-all.ru/3.3/faq/programming.html#how-can-i-sort-one-list-by-values-from-another-list)66  - [Объекты](https://python-all.ru/3.3/faq/programming.html#objects)6768    - [Что такое класс?](https://python-all.ru/3.3/faq/programming.html#what-is-a-class)69    - [Что такое метод?](https://python-all.ru/3.3/faq/programming.html#what-is-a-method)70    - [Что такое self?](https://python-all.ru/3.3/faq/programming.html#what-is-self)71    - [Как проверить, является ли объект экземпляром данного класса или его подкласса?](https://python-all.ru/3.3/faq/programming.html#how-do-i-check-if-an-object-is-an-instance-of-a-given-class-or-of-a-subclass-of-it)72    - [Что такое делегирование?](https://python-all.ru/3.3/faq/programming.html#what-is-delegation)73    - [Как вызвать метод, определённый в базовом классе, из производного класса, который его переопределяет?](https://python-all.ru/3.3/faq/programming.html#how-do-i-call-a-method-defined-in-a-base-class-from-a-derived-class-that-overrides-it)74    - [Как организовать код, чтобы было проще изменить базовый класс?](https://python-all.ru/3.3/faq/programming.html#how-can-i-organize-my-code-to-make-it-easier-to-change-the-base-class)75    - [Как создать статические данные класса и статические методы класса?](https://python-all.ru/3.3/faq/programming.html#how-do-i-create-static-class-data-and-static-class-methods)76    - [Как перегрузить конструкторы (или методы) в Python?](https://python-all.ru/3.3/faq/programming.html#how-can-i-overload-constructors-or-methods-in-python)77    - [Я пытаюсь использовать \_\_spam и получаю ошибку о \_SomeClassName\_\_spam.](https://python-all.ru/3.3/faq/programming.html#i-try-to-use-spam-and-i-get-an-error-about-someclassname-spam)78    - [Мой класс определяет \_\_del\_\_, но он не вызывается при удалении объекта.](https://python-all.ru/3.3/faq/programming.html#my-class-defines-del-but-it-is-not-called-when-i-delete-the-object)79    - [Как получить список всех экземпляров данного класса?](https://python-all.ru/3.3/faq/programming.html#how-do-i-get-a-list-of-all-instances-of-a-given-class)80    - [Почему результат `id()` кажется неуникальным?](https://python-all.ru/3.3/faq/programming.html#why-does-the-result-of-id-appear-to-be-not-unique)81  - [Модули](https://python-all.ru/3.3/faq/programming.html#modules)8283    - [Как создать .pyc-файл?](https://python-all.ru/3.3/faq/programming.html#how-do-i-create-a-pyc-file)84    - [Как узнать имя текущего модуля?](https://python-all.ru/3.3/faq/programming.html#how-do-i-find-the-current-module-name)85    - [Как сделать так, чтобы модули импортировали друг друга?](https://python-all.ru/3.3/faq/programming.html#how-can-i-have-modules-that-mutually-import-each-other)86    - [\_\_import\_\_(‘x.y.z’) возвращает \<module ‘x’\>; как получить z?](https://python-all.ru/3.3/faq/programming.html#import-x-y-z-returns-module-x-how-do-i-get-z)87    - [При редактировании импортированного модуля и его повторном импорте изменения не отображаются. Почему это происходит?](https://python-all.ru/3.3/faq/programming.html#when-i-edit-an-imported-module-and-reimport-it-the-changes-don-t-show-up-why-does-this-happen)8889## [Общие вопросы](https://python-all.ru/3.3/faq/programming.html#id2)9091### [Существует ли отладчик на уровне исходного кода с точками останова, пошаговым выполнением и т. д.?](https://python-all.ru/3.3/faq/programming.html#id3)9293Да.9495The pdb module is a simple but adequate console-mode debugger for Python. It is part of the standard Python library, and is [`documented in the Library Reference Manual`](https://python-all.ru/3.3/library/pdb.html#module-pdb). You can also write your own debugger by using the code for pdb as an example.9697Интерактивная среда разработки IDLE, входящая в стандартный дистрибутив Python (обычно доступна как Tools/scripts/idle), включает графический отладчик. Документация по отладчику IDLE находится по адресу [http://www.python.org/idle/doc/idle2.html#Debugger](https://python-all.ru/3.3/faq/programming.html).9899PythonWin – это IDE для Python, включающая графический отладчик на основе pdb. Отладчик PythonWin раскрашивает точки останова и обладает рядом полезных возможностей, таких как отладка программ, не являющихся программами PythonWin. PythonWin доступен как часть проекта [Python for Windows Extensions](https://python-all.ru/3.3/faq/programming.html), а также в составе дистрибутива ActivePython (см. [http://www.activestate.com/Products/ActivePython/index.html](https://python-all.ru/3.3/faq/programming.html)).100101[Boa Constructor](https://python-all.ru/3.3/faq/programming.html) – это среда разработки и конструктор графического интерфейса на основе wxWidgets. Он предоставляет визуальное создание и редактирование фреймов, инспектор объектов, различные представления исходного кода, включая обозреватели объектов, иерархии наследования, HTML-документацию, сгенерированную из строк документации, расширенный отладчик, встроенную справку и поддержку Zope.102103[Eric](https://python-all.ru/3.3/faq/programming.html) – это IDE, построенная на PyQt и компоненте редактирования Scintilla.104105Pydb – это версия стандартного отладчика Python pdb, модифицированная для использования с DDD (Data Display Debugger) – популярным графическим интерфейсом отладчика. Pydb можно найти по адресу [http://bashdb.sourceforge.net/pydb/](https://python-all.ru/3.3/faq/programming.html), а DDD – по адресу [http://www.gnu.org/software/ddd](https://python-all.ru/3.3/faq/programming.html).106107Существует ряд коммерческих IDE для Python, включающих графические отладчики. Среди них:108109- Wing IDE ([http://wingware.com/](https://python-all.ru/3.3/faq/programming.html))110- Komodo IDE ([http://www.activestate.com/Products/Komodo](https://python-all.ru/3.3/faq/programming.html))111112### [Существует ли инструмент для поиска ошибок или выполнения статического анализа?](https://python-all.ru/3.3/faq/programming.html#id4)113114Да.115116PyChecker – это инструмент статического анализа, который находит ошибки в исходном коде Python и предупреждает о сложности и стиле кода. PyChecker можно получить по адресу [http://pychecker.sf.net](https://python-all.ru/3.3/faq/programming.html).117118[Pylint](https://python-all.ru/3.3/faq/programming.html) – ещё один инструмент, который проверяет, соответствует ли модуль стандарту кодирования, а также позволяет писать плагины для добавления собственных функций. В дополнение к поиску ошибок, выполняемому PyChecker, Pylint предлагает несколько дополнительных возможностей, таких как проверка длины строки, соответствие имён переменных вашему стандарту кодирования, полная реализация объявленных интерфейсов и другие. На странице [http://www.logilab.org/card/pylint\_manual](https://python-all.ru/3.3/faq/programming.html) приведён полный список возможностей Pylint.119120### [Как создать автономный исполняемый файл из скрипта Python?](https://python-all.ru/3.3/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/3.3/faq/programming.html)131132Ещё один – [SQFREEZE](https://python-all.ru/3.3/faq/programming.html) Кристиана Тисмера, который добавляет байт-код к специально подготовленному интерпретатору Python, способному найти байт-код в исполняемом файле.133134Другие инструменты включают [Squeeze](https://python-all.ru/3.3/faq/programming.html) Фредрика Лунда и [cx\_Freeze](https://python-all.ru/3.3/faq/programming.html) Энтони Туйнинги.135136### [Существуют ли стандарты кодирования или руководство по стилю для программ на Python?](https://python-all.ru/3.3/faq/programming.html#id6)137138Да. Требуемый стиль оформления кода для модулей стандартной библиотеки описан в документе [**PEP 8**](https://python-all.ru/3.3/faq/programming.html).139140## [Ядро языка](https://python-all.ru/3.3/faq/programming.html#id7)141142### [Почему возникает UnboundLocalError, если переменная содержит значение?](https://python-all.ru/3.3/faq/programming.html#id8)143144Может быть неожиданным получить ошибку UnboundLocalError в ранее работавшем коде после добавления оператора присваивания где-то в теле функции.145146Этот код:147148```python149>>> x = 10150>>> def bar():151...     print(x)152>>> bar()15310154```155156работает, но этот код:157158```python159>>> x = 10160>>> def foo():161...     print(x)162...     x += 1163```164165приводит к ошибке UnboundLocalError:166167```python168>>> foo()169Traceback (most recent call last):170  ...171UnboundLocalError: local variable 'x' referenced before assignment172```173174Это происходит потому, что когда вы присваиваете значение переменной в некоторой области видимости, эта переменная становится локальной для этой области и скрывает любую одноимённую переменную из внешней области. Поскольку последний оператор в foo присваивает новое значение `x`, компилятор распознаёт её как локальную переменную. Следовательно, когда более ранний `print(x)` пытается вывести неинициализированную локальную переменную, возникает ошибка.175176В приведённом выше примере можно получить доступ к переменной внешней области, объявив её глобальной:177178```python179>>> x = 10180>>> def foobar():181...     global x182...     print(x)183...     x += 1184>>> foobar()18510186```187188Такое явное объявление необходимо, чтобы напомнить: в отличие от внешне похожей ситуации с переменными класса и экземпляра, здесь фактически изменяется значение переменной во внешней области видимости:189190```python191>>> print(x)19211193```194195Аналогичное действие можно выполнить во вложенной области видимости с помощью ключевого слова [`nonlocal`](https://python-all.ru/3.3/reference/simple_stmts.html#nonlocal):196197```python198>>> def foo():199...    x = 10200...    def bar():201...        nonlocal x202...        print(x)203...        x += 1204...    bar()205...    print(x)206>>> foo()2071020811209```210211### [Каковы правила использования локальных и глобальных переменных в Python?](https://python-all.ru/3.3/faq/programming.html#id9)212213В Python переменные, которые используются только внутри функции, неявно считаются глобальными. Если переменной присваивается новое значение в любом месте тела функции, она считается локальной. Если переменной когда-либо присваивается новое значение внутри функции, она неявно является локальной, и её нужно явно объявить как 'global'.214215Хотя сначала это может показаться удивительным, небольшое размышление всё объясняет. С одной стороны, требование [`global`](https://python-all.ru/3.3/reference/simple_stmts.html#global) для присваиваемых переменных предотвращает непреднамеренные побочные эффекты. С другой стороны, если бы `global` требовалось для всех глобальных ссылок, вам пришлось бы использовать `global` постоянно. Пришлось бы объявлять как глобальные каждую ссылку на встроенную функцию или компонент импортированного модуля. Такой беспорядок свёл бы на нет полезность объявления `global` для выявления побочных эффектов.216217### [Почему лямбды, определённые в цикле с разными значениями, все возвращают один и тот же результат?](https://python-all.ru/3.3/faq/programming.html#id10)218219Предположим, что с помощью цикла for определяется несколько разных лямбд (или даже обычных функций), например:220221```python222>>> squares = []223>>> for x in range(5):224...    squares.append(lambda: x**2)225```226227В результате получается список, содержащий 5 лямбда-функций, вычисляющих `x**2`. Можно ожидать, что при вызове они вернут соответственно `0`, `1`, `4`, `9` и `16`. Однако когда вы попробуете, то увидите, что все они возвращают `16`:228229```python230>>> squares[2]()23116232>>> squares[4]()23316234```235236Это происходит потому, что `x` не является локальной для лямбда-функций, а определена во внешней области видимости и доступна при вызове лямбды, а не при её определении. В конце цикла значение `x` равно `4`, поэтому все функции теперь возвращают `4**2`, то есть `16`. Вы также можете убедиться в этом, изменив значение `x` и посмотрев, как изменятся результаты лямбд:237238```python239>>> x = 8240>>> squares[2]()24164242```243244Чтобы избежать этого, нужно сохранить значения в переменных, локальных для лямбд, чтобы они не зависели от значения глобальной `x`:245246```python247>>> squares = []248>>> for x in range(5):249...    squares.append(lambda n=x: n**2)250```251252Здесь `n=x` создаёт новую переменную `n`, локальную для лямбды и вычисляемую при её определении, так что она имеет то же значение, что и `x` в тот момент цикла. Это означает, что значение `n` будет равно `0` в первой лямбде, `1` во второй, `2` в третьей и так далее. Следовательно, каждая лямбда теперь вернёт правильный результат:253254```python255>>> squares[2]()2564257>>> squares[4]()25816259```260261Обратите внимание: такое поведение присуще не только лямбдам, но и обычным функциям.262263### [Как разделять глобальные переменные между модулями?](https://python-all.ru/3.3/faq/programming.html#id11)264265Общепринятый способ обмена информацией между модулями в рамках одной программы – создать специальный модуль (часто называемый config или cfg). Достаточно импортировать модуль config во все модули приложения, и он станет доступен как глобальное имя. Поскольку у каждого модуля существует только один экземпляр, любые изменения объекта модуля отражаются везде. Например:266267config.py:268269```python270x = 0   # Значение по умолчанию для параметра конфигурации 'x'271```272273mod.py:274275```python276import config277config.x = 1278```279280main.py:281282```python283import config284import mod285print(config.x)286```287288Обратите внимание: использование модуля также является основой для реализации паттерна Singleton по той же причине.289290### [Каковы «лучшие практики» использования import в модуле?](https://python-all.ru/3.3/faq/programming.html#id12)291292В общем случае не используйте `from modulename import *`. Это загромождает пространство имён импортирующего модуля. Некоторые избегают такого стиля даже для тех немногих модулей, которые были спроектированы для импорта таким образом. К таким модулям относятся [`tkinter`](https://python-all.ru/3.3/library/tkinter.html#module-tkinter) и [`threading`](https://python-all.ru/3.3/library/threading.html#module-threading).293294Импортируйте модули в начале файла. Так сразу становится ясно, какие ещё модули требуются вашему коду, и не возникает вопросов, находится ли имя модуля в области видимости. Использование одного импорта на строку упрощает добавление и удаление импортов, а использование нескольких импортов в одной строке экономит место на экране.295296Рекомендуется импортировать модули в следующем порядке:2972981. модули стандартной библиотеки – например, `sys`, `os`, `getopt`, `re`2992. модули сторонних библиотек (всё, установленное в каталог site-packages Python), например mx.DateTime, ZODB, PIL.Image и т.д.3003. модули локальной разработки301302Никогда не используйте относительные импорты пакетов. Если вы пишете код, находящийся в модуле `package.sub.m1`, и хотите импортировать `package.sub.m2`, не пишите просто `from . import m2`, даже если это допустимо. Вместо этого пишите `from package.sub import m2`. Подробнее см. [**PEP 328**](https://python-all.ru/3.3/faq/programming.html).303304Иногда импорты приходится переносить внутрь функции или класса, чтобы избежать проблем с циклическими импортами. Gordon McMillan говорит:305306> Циклические импорты нормально работают, когда оба модуля используют форму импорта “import \<module\>”. Они перестают работать, когда второй модуль пытается получить имя из первого (“from module import name”), и импорт находится на верхнем уровне. Это происходит потому, что имена в первом модуле ещё недоступны, так как первый модуль занят импортом второго.307308В этом случае, если второй модуль используется только в одной функции, импорт можно легко перенести в эту функцию. К моменту вызова импорта первый модуль уже завершит инициализацию, и второй модуль сможет выполнить свой импорт.309310Также может потребоваться перенести импорты из верхнего уровня кода, если некоторые модули являются платформозависимыми. В таком случае может быть невозможно импортировать все модули в начале файла. Тогда хорошим решением будет импортировать нужные модули в соответствующем платформозависимом коде.311312Переносите импорты в локальную область видимости, например внутрь определения функции, только если это необходимо для решения проблемы, такой как избежание циклического импорта или попытка сократить время инициализации модуля. Этот метод особенно полезен, если многие импорты не нужны в зависимости от того, как выполняется программа. Возможно, вы также захотите перенести импорты в функцию, если модули используются только внутри неё. Обратите внимание, что загрузка модуля в первый раз может быть дорогой из-за однократной инициализации модуля, но повторная загрузка модуля практически бесплатна – требуется лишь несколько поисков в словаре. Даже если имя модуля вышло из области видимости, модуль, вероятно, доступен в [`sys.modules`](https://python-all.ru/3.3/library/sys.html#sys.modules).313314Если модуль используется только экземплярами определённого класса, то разумно импортировать этот модуль в методе `__init__` класса и затем присвоить модуль переменной экземпляра, чтобы модуль был всегда доступен (через эту переменную экземпляра) в течение времени жизни объекта. Обратите внимание: чтобы отложить импорт до момента создания экземпляра класса, импорт должен находиться внутри метода. Размещение импорта внутри класса, но вне какого-либо метода, всё равно приведёт к тому, что импорт произойдёт при инициализации модуля.315316### [Как передать необязательные или именованные параметры из одной функции в другую?](https://python-all.ru/3.3/faq/programming.html#id13)317318Соберите аргументы с помощью спецификаторов `*` и `**` в списке параметров функции; это даст позиционные аргументы в виде кортежа, а именованные – в виде словаря. Затем вы можете передать эти аргументы при вызове другой функции, используя `*` и `**`:319320```python321def f(x, *args, **kwargs):322    ...323    kwargs['width'] = '14.3c'324    ...325    g(x, *args, **kwargs)326```327328### [В чём разница между аргументами и параметрами?](https://python-all.ru/3.3/faq/programming.html#id14)329330[*Параметры*](https://python-all.ru/3.3/glossary.html#term-parameter) определяются именами, которые указаны в определении функции, тогда как [*аргументы*](https://python-all.ru/3.3/glossary.html#term-argument) – это значения, которые передаются функции при её вызове. Параметры определяют, какие типы аргументов может принимать функция. Например, для такого определения функции:331332```python333def func(foo, bar=None, **kwargs):334    pass335```336337*foo*, *bar* и *kwargs* – это параметры `func`. Однако при вызове `func`, например:338339```python340func(42, bar=314, extra=somevar)341```342343значения `42`, `314` и `somevar` являются аргументами.344345### [Как написать функцию с выходными параметрами (передача по ссылке)?](https://python-all.ru/3.3/faq/programming.html#id15)346347Помните, что в Python аргументы передаются по присваиванию. Поскольку присваивание лишь создает ссылки на объекты, между именем аргумента в вызывающей и вызываемой функции нет псевдонима, а значит, нет и передачи по ссылке как таковой. Желаемого эффекта можно достичь несколькими способами.3483491. Возвращая кортеж результатов:350351   ```python352   def func2(a, b):353       a = 'new-value'        # a и b – локальные имена354       b = b + 1              # присвоены новым объектам355       return a, b            # вернуть новые значения356357   x, y = 'old-value', 99358   x, y = func2(x, y)359   print(x, y)                # вывод: new-value 100360   ```361362   Это почти всегда самое понятное решение.3632. С помощью глобальных переменных. Это не потокобезопасно и не рекомендуется.3643. Передавая изменяемый (изменяемый на месте) объект:365366   ```python367   def func1(a):368       a[0] = 'new-value'     # 'a' ссылается на изменяемый список369       a[1] = a[1] + 1        # изменяет общий объект370371   args = ['old-value', 99]372   func1(args)373   print(args[0], args[1])    # вывод: new-value 100374   ```3754. Передавая словарь, который будет изменён:376377   ```python378   def func3(args):379       args['a'] = 'new-value'     # args – изменяемый словарь380       args['b'] = args['b'] + 1   # изменить его на месте381382   args = {'a':' old-value', 'b': 99}383   func3(args)384   print(args['a'], args['b'])385   ```3865. Или объединив значения в экземпляре класса:387388   ```python389   class callByRef:390       def __init__(self, **args):391           for (key, value) in args.items():392               setattr(self, key, value)393394   def func4(args):395       args.a = 'new-value'        # args – изменяемый callByRef396       args.b = args.b + 1         # изменить объект на месте397398   args = callByRef(a='old-value', b=99)399   func4(args)400   print(args.a, args.b)401   ```402403   Почти никогда нет веской причины усложнять до такой степени.404405Лучший выбор – вернуть кортеж, содержащий несколько результатов.406407### [Как сделать функцию высшего порядка в Python?](https://python-all.ru/3.3/faq/programming.html#id16)408409У вас есть два варианта: использовать вложенные области видимости или вызываемые объекты. Например, предположим, вы хотите определить `linear(a,b)`, которая возвращает функцию `f(x)`, вычисляющую значение `a*x+b`. Использование вложенных областей видимости:410411```python412def linear(a, b):413    def result(x):414        return a * x + b415    return result416```417418Или используя вызываемый объект:419420```python421class linear:422423    def __init__(self, a, b):424        self.a, self.b = a, b425426    def __call__(self, x):427        return self.a * x + self.b428```429430В обоих случаях431432```python433taxes = linear(0.3, 2)434```435436даёт вызываемый объект, где `taxes(10e6) == 0.3 * 10e6 + 2`.437438Подход с вызываемым объектом имеет недостаток: он немного медленнее и\\nприводит к чуть более длинному коду. Однако обратите внимание, что набор вызываемых объектов\\nможет разделять свою сигнатуру через наследование:439440```python441class exponential(linear):442    # __init__ унаследован443    def __call__(self, x):444        return self.a * (x ** self.b)445```446447Объект может инкапсулировать состояние для нескольких методов:448449```python450class counter:451452    value = 0453454    def set(self, x):455        self.value = x456457    def up(self):458        self.value = self.value + 1459460    def down(self):461        self.value = self.value - 1462463count = counter()464inc, dec, reset = count.up, count.down, count.set465```466467Здесь `inc()`, `dec()` и `reset()` ведут себя как функции, которые совместно используют одну и ту же переменную-счётчик.468469### [Как скопировать объект в Python?](https://python-all.ru/3.3/faq/programming.html#id17)470471В общем случае попробуйте [`copy.copy()`](https://python-all.ru/3.3/library/copy.html#copy.copy) или [`copy.deepcopy()`](https://python-all.ru/3.3/library/copy.html#copy.deepcopy). Не все объекты можно копировать, но большинство можно.472473Некоторые объекты копировать проще. У словарей есть метод [`copy()`](https://python-all.ru/3.3/library/stdtypes.html#dict.copy):474475```python476newdict = olddict.copy()477```478479Последовательности можно скопировать срезом:480481```python482new_l = l[:]483```484485### [Как найти методы или атрибуты объекта?](https://python-all.ru/3.3/faq/programming.html#id18)486487Для экземпляра x пользовательского класса `dir(x)` возвращает отсортированный по алфавиту список имён, содержащий атрибуты экземпляра, а также методы и атрибуты, определённые в его классе.488489### [Как код может узнать имя объекта?](https://python-all.ru/3.3/faq/programming.html#id19)490491Вообще говоря, нет, потому что у объектов на самом деле нет имён. По сути, присваивание всегда связывает имя со значением; то же верно для инструкций `def` и `class`, но в этом случае значением является вызываемый объект. Рассмотрим следующий код:492493```python494class A:495    pass496497B = A498499a = B()500b = a501print(b)502<__main__.A object at 0x16D07CC>503print(a)504<__main__.A object at 0x16D07CC>505```506507Можно утверждать, что у класса есть имя: даже если он привязан к двум именам и вызывается через имя B, созданный экземпляр всё равно будет определён как экземпляр класса A. Однако невозможно сказать, какое имя у экземпляра – a или b, поскольку оба имени привязаны к одному и тому же значению.508509Вообще говоря, коду не требуется «знать имена» конкретных значений. Если вы не пишете намеренно интроспективные программы, это обычно указывает на то, что стоит изменить подход.510511В comp.lang.python Фредрик Лунд однажды привёл отличную аналогию в ответ на этот вопрос:512513> Точно так же, как вы узнаёте имя кота, которого нашли на крыльце: сам кот (объект) не может сказать вам своего имени, и ему на это всё равно – так что единственный способ узнать, как его зовут, – спросить всех соседей (пространства имён), не их ли это кот (объект)...514>515> ...и не удивляйтесь, если окажется, что он известен под многими именами – или вообще без имени!516517### [Что не так с приоритетом оператора-запятой?](https://python-all.ru/3.3/faq/programming.html#id20)518519Запятая в Python – не оператор. Рассмотрим такой сеанс:520521```python522>>> "a" in "b", "a"523(False, 'a')524```525526Поскольку запятая – не оператор, а разделитель между выражениями, приведённый выше код выполняется так, как если бы вы ввели:527528```python529("a" in "b"), "a"530```531532а не:533534```python535"a" in ("b", "a")536```537538То же самое верно для различных операторов присваивания (`=`, `+=` и т. д.). Они не являются операторами в полном смысле, а представляют собой синтаксические разделители в операторах присваивания.539540### [Существует ли эквивалент тернарного оператора ”?:” из C?](https://python-all.ru/3.3/faq/programming.html#id21)541542Да, существует. Синтаксис следующий:543544```python545[on_true] if [expression] else [on_false]546547x, y = 50, 25548small = x if x < y else y549```550551До введения этого синтаксиса в Python 2.5 распространённым приёмом было использование логических операторов:552553```python554[expression] and [on_true] or [on_false]555```556557Однако этот приём небезопасен, так как может дать неверный результат, если *on\_true* имеет ложное булево значение. Поэтому всегда лучше использовать форму `... if ... else ...`.558559### [Можно ли писать запутанные однострочники на Python?](https://python-all.ru/3.3/faq/programming.html#id22)560561Да. Обычно это делается путём вложения [`lambda`](https://python-all.ru/3.3/reference/expressions.html#lambda) в [`lambda`](https://python-all.ru/3.3/reference/expressions.html#lambda). Смотрите следующие три примера, автор Ulf Bartelt:562563```python564from functools import reduce565566# Простые числа < 1000567print(list(filter(None,map(lambda y:y*reduce(lambda x,y:x*y!=0,568map(lambda x,y=y:y%x,range(2,int(pow(y,0.5)+1))),1),range(2,1000)))))569570# Первые 10 чисел Фибоначчи571print(list(map(lambda x,f=lambda x,f:(f(x-1,f)+f(x-2,f)) if x>1 else 1:572f(x,f), range(10))))573574# Множество Мандельброта575print((lambda Ru,Ro,Iu,Io,IM,Sx,Sy:reduce(lambda x,y:x+y,map(lambda y,576Iu=Iu,Io=Io,Ru=Ru,Ro=Ro,Sy=Sy,L=lambda yc,Iu=Iu,Io=Io,Ru=Ru,Ro=Ro,i=IM,577Sx=Sx,Sy=Sy:reduce(lambda x,y:x+y,map(lambda x,xc=Ru,yc=yc,Ru=Ru,Ro=Ro,578i=i,Sx=Sx,F=lambda xc,yc,x,y,k,f=lambda xc,yc,x,y,k,f:(k<=0)or (x*x+y*y579>=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(58064+F(Ru+x*(Ro-Ru)/Sx,yc,0,0,i)),range(Sx))):L(Iu+y*(Io-Iu)/Sy),range(Sy581))))(-2.1, 0.7, -1.2, 1.2, 30, 80, 24))582#    \___ ___/  \___ ___/  |   |   |__ линии на экране583#        V          V      |   |______ столбцы на экране584#        |          |      |__________ максимум "iterations"585#        |          |_________________ диапазон по оси Y586#        |____________________________ диапазон по оси X587```588589Не пытайтесь повторить это дома, дети!590591## [Числа и строки](https://python-all.ru/3.3/faq/programming.html#id23)592593### [Как задать шестнадцатеричные и восьмеричные целые числа?](https://python-all.ru/3.3/faq/programming.html#id24)594595Чтобы задать восьмеричное число, поставьте перед восьмеричным значением ноль, а затем строчную или прописную букву «o». Например, чтобы присвоить переменной «a» восьмеричное значение «10» (8 в десятичной системе), введите:596597```python598>>> a = 0o10599>>> a6008601```602603Шестнадцатеричные числа задаются так же просто. Просто поставьте перед шестнадцатеричным числом ноль, а затем строчную или прописную «x». Шестнадцатеричные цифры можно указывать в нижнем или верхнем регистре. Например, в интерпретаторе Python:604605```python606>>> a = 0xa5607>>> a608165609>>> b = 0XB2610>>> b611178612```613614### [Почему -22 // 10 возвращает -3?](https://python-all.ru/3.3/faq/programming.html#id25)615616Это в первую очередь обусловлено желанием, чтобы `i % j` имел тот же знак, что и `j`. Если вы хотите этого, а также хотите:617618```python619i == (i // j) * j + (i % j)620```621622тогда целочисленное деление должно возвращать floor (целую часть с округлением вниз). C также требует выполнения этого тождества, и тогда компиляторы, которые обрезают `i // j`, должны сделать так, чтобы `i % j` имел тот же знак, что и `i`.623624Существует мало реальных случаев использования `i % j`, когда `j` отрицательно. Когда `j` положительно, таких случаев много, и практически во всех из них полезнее, чтобы `i % j` было равно `>= 0`. Если часы показывают 10 сейчас, что они показывали 200 часов назад? `-190 % 12 == 2` полезно; `-190 % 12 == -10` – это ошибка, которая только и ждёт, чтобы проявиться.625626### [Как преобразовать строку в число?](https://python-all.ru/3.3/faq/programming.html#id26)627628Для целых чисел используйте встроенный конструктор типа [`int()`](https://python-all.ru/3.3/library/functions.html#int), например `int('144') == 144`. Аналогично [`float()`](https://python-all.ru/3.3/library/functions.html#float) преобразует в число с плавающей точкой, например `float('144') == 144.0`.629630По умолчанию эти функции интерпретируют число как десятичное, так что `int('0144') == 144` и `int('0x144')` вызывают [`ValueError`](https://python-all.ru/3.3/library/exceptions.html#ValueError). `int(string, base)` принимает основание системы счисления в качестве второго необязательного аргумента, поэтому `int('0x144', 16) == 324`. Если указать основание 0, число интерпретируется по правилам Python: ведущий '0' означает восьмеричное, а '0x' – шестнадцатеричное.631632Не используйте встроенную функцию [`eval()`](https://python-all.ru/3.3/library/functions.html#eval), если вам нужно только преобразовать строки в числа. [`eval()`](https://python-all.ru/3.3/library/functions.html#eval) будет значительно медленнее и представляет угрозу безопасности: кто-то может передать вам Python-выражение с нежелательными побочными эффектами. Например, кто-то может передать `__import__('os').system("rm -rf $HOME")`, что удалит ваш домашний каталог.633634[`eval()`](https://python-all.ru/3.3/library/functions.html#eval) также интерпретирует числа как Python-выражения, так что, например, `eval('09')` вызывает синтаксическую ошибку, поскольку Python не допускает ведущий ноль в десятичных числах (кроме самого '0').635636### [Как преобразовать число в строку?](https://python-all.ru/3.3/faq/programming.html#id27)637638Чтобы преобразовать, например, число 144 в строку '144', используйте встроенный конструктор типа [`str()`](https://python-all.ru/3.3/library/stdtypes.html#str). Если нужны шестнадцатеричное или восьмеричное представление, используйте встроенные функции [`hex()`](https://python-all.ru/3.3/library/functions.html#hex) или [`oct()`](https://python-all.ru/3.3/library/functions.html#oct). Для расширенного форматирования см. раздел [*String Formatting*](https://python-all.ru/3.3/library/string.html#string-formatting), например, `"{:04d}".format(144)` даёт `'0144'`, а `"{:.3f}".format(1/3)` даёт `'0.333'`.639640### [Как изменить строку на месте?](https://python-all.ru/3.3/faq/programming.html#id28)641642Нельзя, потому что строки неизменяемы. В большинстве случаев следует просто собрать новую строку из нужных частей. Однако если нужен объект, способный изменять unicode-данные на месте, попробуйте использовать объект [`io.StringIO`](https://python-all.ru/3.3/library/io.html#io.StringIO) или модуль [`array`](https://python-all.ru/3.3/library/array.html#module-array):643644```python645>>> import io646>>> s = "Hello, world"647>>> sio = io.StringIO(s)648>>> sio.getvalue()649'Hello, world'650>>> sio.seek(7)6517652>>> sio.write("there!")6536654>>> sio.getvalue()655'Hello, there!'656657>>> import array658>>> a = array.array('u', s)659>>> print(a)660array('u', 'Hello, world')661>>> a[0] = 'y'662>>> print(a)663array('u', 'yello, world')664>>> a.tounicode()665'yello, world'666```667668### [Как использовать строки для вызова функций/методов?](https://python-all.ru/3.3/faq/programming.html#id29)669670Существует несколько приёмов.671672- Лучший из них – использовать словарь, сопоставляющий строки с функциями. Главное преимущество этого подхода в том, что строки не обязаны совпадать с именами функций. Это также основной способ эмуляции конструкции case:673674  ```python675  def a():676      pass677678  def b():679      pass680681  dispatch = {'go': a, 'stop': b}  # Обратите внимание на отсутствие скобок для функций682683  dispatch[get_input()]()  # Обратите внимание на завершающие скобки для вызова функции684  ```685- Используйте встроенную функцию [`getattr()`](https://python-all.ru/3.3/library/functions.html#getattr):686687  ```python688  import foo689  getattr(foo, 'bar')()690  ```691692  Обратите внимание, что [`getattr()`](https://python-all.ru/3.3/library/functions.html#getattr) работает с любым объектом, включая классы, экземпляры классов, модули и т.д.693694  Это используется в нескольких местах стандартной библиотеки, например:695696  ```python697  class Foo:698      def do_foo(self):699          ...700701      def do_bar(self):702          ...703704  f = getattr(foo_instance, 'do_' + opname)705  f()706  ```707- Используйте [`locals()`](https://python-all.ru/3.3/library/functions.html#locals) или [`eval()`](https://python-all.ru/3.3/library/functions.html#eval) для разрешения имени функции:708709  ```python710  def myFunc():711      print("hello")712713  fname = "myFunc"714715  f = locals()[fname]716  f()717718  f = eval(fname)719  f()720  ```721722  Примечание: использование [`eval()`](https://python-all.ru/3.3/library/functions.html#eval) медленно и опасно. Если у вас нет полного контроля над содержимым строки, кто-то может передать строку, которая приведёт к выполнению произвольной функции.723724### [Существует ли аналог функции chomp() из Perl для удаления завершающих символов новой строки из строк?](https://python-all.ru/3.3/faq/programming.html#id30)725726Вы можете использовать `S.rstrip("\r\n")`, чтобы удалить все символы конца строки из конца строки `S`, не удаляя при этом другие пробельные символы в конце. Если строка `S` содержит несколько строк с несколькими пустыми строками в конце, будут удалены символы конца строки для всех пустых строк:727728```python729>>> lines = ("line 1 \r\n"730...          "\r\n"731...          "\r\n")732>>> lines.rstrip("\n\r")733'line 1 '734```735736Так как это обычно требуется только при построчном чтении текста, использование `S.rstrip()` таким образом вполне эффективно.737738### [Существует ли аналог функций scanf() или sscanf()?](https://python-all.ru/3.3/faq/programming.html#id31)739740Прямого аналога нет.741742Для простого разбора ввода обычно проще всего разбить строку на слова, разделённые пробелами, с помощью метода [`split()`](https://python-all.ru/3.3/library/stdtypes.html#str.split) строковых объектов, а затем преобразовать десятичные строки в числа с помощью [`int()`](https://python-all.ru/3.3/library/functions.html#int) или [`float()`](https://python-all.ru/3.3/library/functions.html#float). `split()` поддерживает необязательный параметр "sep", который полезен, если строка использует не пробелы в качестве разделителя.743744Для более сложного разбора ввода регулярные выражения мощнее, чем `sscanf()` в C, и лучше подходят для этой задачи.745746### [Что означает ошибка UnicodeDecodeError или UnicodeEncodeError?](https://python-all.ru/3.3/faq/programming.html#id32)747748Смотрите [*Unicode HOWTO*](https://python-all.ru/3.3/howto/unicode.html#unicode-howto).749750## [Производительность](https://python-all.ru/3.3/faq/programming.html#id33)751752### [Моя программа слишком медленная. Как её ускорить?](https://python-all.ru/3.3/faq/programming.html#id34)753754В целом это непростой вопрос. Во-первых, вот список того, что стоит помнить, прежде чем углубляться:755756- Характеристики производительности различаются в разных реализациях Python. В этом FAQ основное внимание уделяется [*CPython*](https://python-all.ru/3.3/glossary.html#term-cpython).757- Поведение может различаться в разных операционных системах, особенно когда речь идёт о вводе-выводе или многопоточности.758- Следует всегда находить узкие места в программе *перед* попытками оптимизировать какой-либо код (см. модуль [`profile`](https://python-all.ru/3.3/library/profile.html#module-profile)).759- Написание бенчмарк-скриптов позволит быстро итерировать при поиске улучшений (см. модуль [`timeit`](https://python-all.ru/3.3/library/timeit.html#module-timeit)).760- Настоятельно рекомендуется иметь хорошее покрытие кода (с помощью модульного тестирования или любой другой методики) перед возможным внесением регрессий, скрытых в сложных оптимизациях.761762Тем не менее, есть много приёмов для ускорения кода на Python. Вот некоторые общие принципы, которые сильно помогают достичь приемлемого уровня производительности:763764- Ускорение алгоритмов (или замена на более быстрые) может принести гораздо большую выгоду, чем попытки рассыпать микрооптимизации по всему коду.765- Используйте правильные структуры данных. Изучите документацию по [*Встроенным типам*](https://python-all.ru/3.3/library/stdtypes.html#bltin-types) и модулю [`collections`](https://python-all.ru/3.3/library/collections.html#module-collections).766- Когда стандартная библиотека предоставляет примитив для выполнения какой-либо задачи, он, скорее всего (хотя и не гарантированно), будет быстрее любой альтернативы, которую вы могли бы придумать. Это вдвойне верно для примитивов, написанных на C, таких как встроенные функции и некоторые типы-расширения. Например, обязательно используйте встроенный метод [`list.sort()`](https://python-all.ru/3.3/library/stdtypes.html#list.sort) или соответствующую функцию [`sorted()`](https://python-all.ru/3.3/library/functions.html#sorted) для сортировки (и посмотрите [мини-руководство по сортировке](https://python-all.ru/3.3/faq/programming.html) для примеров умеренно продвинутого использования).767- Абстракции обычно создают косвенность и заставляют интерпретатор работать больше. Если уровни косвенности перевешивают объём полезной работы, программа будет медленнее. Следует избегать чрезмерной абстракции, особенно в виде крошечных функций или методов (которые также часто вредят читаемости).768769Если вы достигли предела возможностей чистого Python, существуют инструменты, которые помогут пойти дальше. Например, [Cython](https://python-all.ru/3.3/faq/programming.html) может скомпилировать слегка изменённую версию кода Python в расширение C и может использоваться на многих разных платформах. Cython может использовать компиляцию (и необязательные аннотации типов), чтобы сделать ваш код значительно быстрее, чем при интерпретации. Если вы уверены в своих навыках программирования на C, вы также можете самостоятельно [*написать модуль расширения на C*](https://python-all.ru/3.3/extending/index.html#extending-index).770771> **См. также**772>773> Вики-страница, посвящённая [советам по производительности](https://python-all.ru/3.3/faq/programming.html).774775### [Как наиболее эффективно объединить много строк?](https://python-all.ru/3.3/faq/programming.html#id35)776777Объекты [`str`](https://python-all.ru/3.3/library/stdtypes.html#str) и [`bytes`](https://python-all.ru/3.3/library/functions.html#bytes) являются неизменяемыми, поэтому конкатенация многих строк неэффективна, так как каждая конкатенация создаёт новый объект. В общем случае общая стоимость выполнения квадратично зависит от общей длины строк.778779Чтобы накопить много объектов [`str`](https://python-all.ru/3.3/library/stdtypes.html#str), рекомендуется поместить их в список и в конце вызвать [`str.join()`](https://python-all.ru/3.3/library/stdtypes.html#str.join):780781```python782chunks = []783for s in my_strings:784    chunks.append(s)785result = ''.join(chunks)786```787788(другой достаточно эффективный приём – использовать [`io.StringIO`](https://python-all.ru/3.3/library/io.html#io.StringIO))789790Чтобы накопить много объектов [`bytes`](https://python-all.ru/3.3/library/functions.html#bytes), рекомендуется расширять объект [`bytearray`](https://python-all.ru/3.3/library/functions.html#bytearray) с помощью конкатенации на месте (оператор `+=`):791792```python793result = bytearray()794for b in my_bytes_objects:795    result += b796```797798## [Последовательности (кортежи/списки)](https://python-all.ru/3.3/faq/programming.html#id36)799800### [Как преобразовывать кортежи и списки друг в друга?](https://python-all.ru/3.3/faq/programming.html#id37)801802Конструктор типа `tuple(seq)` преобразует любую последовательность (на самом деле, любой итерируемый объект) в кортеж с теми же элементами в том же порядке.803804Например, `tuple([1, 2, 3])` даёт `(1, 2, 3)`, а `tuple('abc')` даёт `('a', 'b', 'c')`. Если аргумент уже является кортежем, то копия не создаётся, а возвращается тот же объект, поэтому вызов [`tuple()`](https://python-all.ru/3.3/library/stdtypes.html#tuple) дёшев, если не уверены, что объект уже кортеж.805806Конструктор типа `list(seq)` преобразует любую последовательность или итерируемый объект в список с теми же элементами в том же порядке. Например, `list((1, 2, 3))` даёт `[1, 2, 3]`, а `list('abc')` даёт `['a', 'b', 'c']`. Если аргумент уже список, то создаётся копия, как и в случае `seq[:]`.807808### [Что такое отрицательный индекс?](https://python-all.ru/3.3/faq/programming.html#id38)809810Последовательности Python индексируются положительными и отрицательными числами. Для положительных чисел 0 – это первый индекс, 1 – второй и т.д. Для отрицательных индексов -1 – это последний, -2 – предпоследний и т.д. Считайте, что `seq[-n]` эквивалентно `seq[len(seq)-n]`.811812Использование отрицательных индексов может быть очень удобным. Например, `S[:-1]` – это вся строка, кроме последнего символа, что полезно для удаления завершающего символа новой строки.813814### [Как перебрать последовательность в обратном порядке?](https://python-all.ru/3.3/faq/programming.html#id39)815816Используйте встроенную функцию [`reversed()`](https://python-all.ru/3.3/library/functions.html#reversed), которая появилась в Python 2.4:817818```python819for x in reversed(sequence):820    ... # выполнить действие с x...821```822823Это не затронет исходную последовательность, а создаст новую копию с обратным порядком для итерации.824825В Python 2.3 можно использовать расширенный синтаксис срезов:826827```python828for x in sequence[::-1]:829    ... # выполнить действие с x...830```831832### [Как удалить дубликаты из списка?](https://python-all.ru/3.3/faq/programming.html#id40)833834См. Python Cookbook, где подробно рассматриваются многие способы сделать это:835836> [http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52560](https://python-all.ru/3.3/faq/programming.html)837838Если перестановка элементов списка не страшна, отсортируйте его, а затем просмотрите с конца, удаляя дубликаты по ходу:839840```python841if mylist:842    mylist.sort()843    last = mylist[-1]844    for i in range(len(mylist)-2, -1, -1):845        if last == mylist[i]:846            del mylist[i]847        else:848            last = mylist[i]849```850851Если все элементы списка могут использоваться как ключи множества (т.е. все они [*хешируемы*](https://python-all.ru/3.3/glossary.html#term-hashable)), это часто быстрее852853```python854mylist = list(set(mylist))855```856857Это преобразует список во множество, удаляя дубликаты, а затем обратно в список.858859### [Как создать массив в Python?](https://python-all.ru/3.3/faq/programming.html#id41)860861Используйте список:862863```python864["this", 1, "is", "an", "array"]865```866867По временно́й сложности списки эквивалентны массивам C или Pascal; основное отличие в том, что список Python может содержать объекты разных типов.868869Модуль `array` также предоставляет методы для создания массивов фиксированных типов с компактным представлением, но они медленнее индексируются, чем списки. Также обратите внимание, что расширения Numeric и другие определяют структуры, похожие на массивы, с различными характеристиками.870871Чтобы получить связные списки в стиле Lisp, можно эмулировать ячейки cons с помощью кортежей:872873```python874lisp_list = ("like",  ("this",  ("example", None) ) )875```876877Если нужна изменяемость, можно использовать списки вместо кортежей. Здесь аналог lisp car – это `lisp_list[0]`, а аналог cdr – `lisp_list[1]`. Делайте так, только если уверены, что это действительно необходимо, потому что обычно это намного медленнее, чем использование списков Python.878879### [Как создать многомерный список?](https://python-all.ru/3.3/faq/programming.html#id42)880881Вероятно, вы пытались создать многомерный массив так:882883```python884>>> A = [[None] * 2] * 3885```886887Если вывести его, выглядит правильно:888889```python890>>> A891[[None, None], [None, None], [None, None]]892```893894Но когда вы присваиваете значение, оно появляется в нескольких местах:895896```python897>>> A[0][0] = 5898>>> A899[[5, None], [5, None], [5, None]]900```901902Причина в том, что размножение списка с помощью `*` не создаёт копии, а только ссылки на существующие объекты. `*3` создаёт список из 3 ссылок на один и тот же список длины два. Изменения в одной строке отразятся во всех строках, что почти наверняка не то, что нужно.903904Рекомендуемый подход – сначала создать список нужной длины, а затем заполнить каждый элемент заново созданным списком:905906```python907A = [None] * 3908for i in range(3):909    A[i] = [None] * 2910```911912Это порождает список, содержащий 3 разных списка длины два. Также можно использовать списковое включение:913914```python915w, h = 2, 3916A = [[None] * w for i in range(h)]917```918919Или можно использовать расширение, предоставляющее тип данных матрица; наиболее известно [Numeric Python](https://python-all.ru/3.3/faq/programming.html).920921### [Как применить метод к последовательности объектов?](https://python-all.ru/3.3/faq/programming.html#id43)922923Используйте списковое включение:924925```python926result = [obj.method() for obj in mylist]927```928929### [Почему a\_tuple\[i\] += \['item'\] вызывает исключение, хотя сложение работает?](https://python-all.ru/3.3/faq/programming.html#id44)930931Это связано с тем, что операторы расширенного присваивания являются *операторами присваивания*, а также с различием между изменяемыми и неизменяемыми объектами в Python.932933Это обсуждение в целом применимо, когда операторы расширенного присваивания применяются к элементам кортежа, указывающим на изменяемые объекты, но в качестве примера мы будем использовать `list` и `+=`.934935Если написать:936937```python938>>> a_tuple = (1, 2)939>>> a_tuple[0] += 1940Traceback (most recent call last):941   ...942TypeError: 'tuple' object does not support item assignment943```944945Причина исключения должна быть сразу ясна: `1` добавляется к объекту, на который указывает `a_tuple[0]` (`1`), в результате получается объект `2`, но когда мы пытаемся присвоить результат вычисления, `2`, элементу `0` кортежа, возникает ошибка, потому что мы не можем изменить то, на что указывает элемент кортежа.946947На самом деле то, что делает этот расширенный оператор присваивания, примерно таково:948949```python950>>> result = a_tuple[0] + 1951>>> a_tuple[0] = result952Traceback (most recent call last):953  ...954TypeError: 'tuple' object does not support item assignment955```956957Ошибку вызывает именно часть присваивания операции, поскольку кортеж неизменяем.958959Если написать что-то вроде:960961```python962>>> a_tuple = (['foo'], 'bar')963>>> a_tuple[0] += ['item']964Traceback (most recent call last):965  ...966TypeError: 'tuple' object does not support item assignment967```968969Исключение несколько более неожиданно, и еще более удивительно то, что, несмотря на ошибку, append сработал:970971```python972>>> a_tuple[0]973['foo', 'item']974```975976Чтобы понять, почему это происходит, нужно знать, что (a) если объект реализует магический метод `__iadd__`, он вызывается при выполнении расширенного присваивания `+=`, и его возвращаемое значение используется в операторе присваивания; и (b) для списков `__iadd__` эквивалентно вызову `extend` для списка и возврату списка. Вот почему мы говорим, что для списков `+=` – это "сокращение" для `list.extend`:977978```python979>>> a_list = []980>>> a_list += [1]981>>> a_list982[1]983```984985Это эквивалентно:986987```python988>>> result = a_list.__iadd__([1])989>>> a_list = result990```991992Объект, на который указывает a\_list, был изменён, и указатель на изменённый объект присваивается обратно `a_list`. Конечный результат присваивания – холостая операция, поскольку это указатель на тот же объект, на который `a_list` указывал ранее, но само присваивание всё же происходит.993994Таким образом, в нашем примере с кортежем происходит то же самое, что и в:995996```python997>>> result = a_tuple[0].__iadd__(['item'])998>>> a_tuple[0] = result999Traceback (most recent call last):1000  ...1001TypeError: 'tuple' object does not support item assignment1002```10031004`__iadd__` выполняется успешно, и список расширяется, но даже несмотря на то, что `result` указывает на тот же объект, на который уже указывает `a_tuple[0]`, это финальное присваивание всё равно приводит к ошибке, потому что кортежи неизменяемы.10051006## [Словари](https://python-all.ru/3.3/faq/programming.html#id45)10071008### [Как сделать, чтобы словарь хранил и выводил ключи в фиксированном порядке?](https://python-all.ru/3.3/faq/programming.html#id46)10091010Используйте [`collections.OrderedDict`](https://python-all.ru/3.3/library/collections.html#collections.OrderedDict).10111012### [Я хочу выполнить сложную сортировку: можно ли сделать преобразование Шварца в Python?](https://python-all.ru/3.3/faq/programming.html#id47)10131014Этот метод, приписываемый Рэндалу Шварцу из сообщества Perl, сортирует элементы списка по метрике, которая отображает каждый элемент в его "значение сортировки". В Python просто используйте аргумент `key` для метода `sort()`:10151016```python1017Isorted = L[:]1018Isorted.sort(key=lambda s: int(s[10:15]))1019```10201021Аргумент `key` появился в Python 2.4, для более старых версий такую сортировку довольно просто выполнить с помощью списковых включений. Чтобы отсортировать список строк по их значениям в верхнем регистре:10221023```python1024tmp1 = [(x.upper(), x) for x in L]  # Преобразование Шварца1025tmp1.sort()1026Usorted = [x[1] for x in tmp1]1027```10281029Чтобы отсортировать по целочисленному значению подполя, расположенного с 10 по 15 позицию в каждой строке:10301031```python1032tmp2 = [(int(s[10:15]), s) for s in L]  # Преобразование Шварца1033tmp2.sort()1034Isorted = [x[1] for x in tmp2]1035```10361037Для версий до 3.0, Isorted также можно вычислить с помощью10381039```python1040def intfield(s):1041    return int(s[10:15])10421043def Icmp(s1, s2):1044    return cmp(intfield(s1), intfield(s2))10451046Isorted = L[:]1047Isorted.sort(Icmp)1048```10491050но поскольку этот метод вызывает `intfield()` много раз для каждого элемента L, он медленнее преобразования Шварца.10511052### [Как отсортировать один список по значениям из другого списка?](https://python-all.ru/3.3/faq/programming.html#id48)10531054Объедините их в итератор кортежей, отсортируйте полученный список, а затем извлеките нужный элемент.10551056```python1057>>> list1 = ["what", "I'm", "sorting", "by"]1058>>> list2 = ["something", "else", "to", "sort"]1059>>> pairs = zip(list1, list2)1060>>> pairs = sorted(pairs)1061>>> pairs1062[("I'm", 'else'), ('by', 'sort'), ('sorting', 'to'), ('what', 'something')]1063>>> result = [x[1] for x in pairs]1064>>> result1065['else', 'sort', 'to', 'something']1066```10671068Альтернатива для последнего шага:10691070```python1071>>> result = []1072>>> for p in pairs: result.append(p[1])1073```10741075Если такой вариант кажется вам более читаемым, возможно, вы предпочтёте его итоговому списковому включению. Однако для длинных списков он почти вдвое медленнее. Почему? Во-первых, операция `append()` требует перераспределения памяти, и хотя для этого используются некоторые уловки, чтобы избегать его каждый раз, время от времени это всё же происходит, и это обходится довольно дорого. Во-вторых, выражение «result.append» требует дополнительного поиска атрибута. В-третьих, из-за необходимости совершать все эти вызовы функций скорость снижается.10761077## [Объекты](https://python-all.ru/3.3/faq/programming.html#id49)10781079### [Что такое класс?](https://python-all.ru/3.3/faq/programming.html#id50)10801081Класс – это конкретный тип объекта, создаваемый при выполнении инструкции class. Объекты классов используются как шаблоны для создания объектов-экземпляров, которые содержат как данные (атрибуты), так и код (методы), характерные для данного типа данных.10821083Класс может быть основан на одном или нескольких других классах, называемых его базовыми классами. Он наследует атрибуты и методы своих базовых классов. Это позволяет последовательно уточнять объектную модель с помощью наследования. У вас может быть общий класс `Mailbox`, предоставляющий базовые методы доступа для почтового ящика, и подклассы, такие как `MboxMailbox`, `MaildirMailbox`, `OutlookMailbox`, которые работают с различными конкретными форматами почтовых ящиков.10841085### [Что такое метод?](https://python-all.ru/3.3/faq/programming.html#id51)10861087Метод – это функция некоторого объекта `x`, которую обычно вызывают как `x.name(аргументы...)`. Методы определяются как функции внутри определения класса:10881089```python1090class C:1091    def meth (self, arg):1092        return arg * 2 + self.attribute1093```10941095### [Что такое self?](https://python-all.ru/3.3/faq/programming.html#id52)10961097Self – это всего лишь общепринятое имя для первого аргумента метода. Метод, определённый как `meth(self, a, b, c)`, следует вызывать как `x.meth(a, b, c)` для некоторого экземпляра `x` класса, в котором находится определение; вызываемый метод будет считать, что его вызвали как `meth(x, a, b, c)`.10981099См. также [*Почему self должно явно использоваться в определениях и вызовах методов?*](https://python-all.ru/3.3/faq/design.html#why-self).11001101### [Как проверить, является ли объект экземпляром данного класса или его подкласса?](https://python-all.ru/3.3/faq/programming.html#id53)11021103Используйте встроенную функцию `isinstance(obj, cls)`. Можно проверить, является ли объект экземпляром любого из нескольких классов, передав кортеж вместо одного класса, например `isinstance(obj, (class1, class2, ...))`, а также можно проверить, является ли объект одним из встроенных типов Python, например `isinstance(obj, str)` или `isinstance(obj, (int, float, complex))`.11041105Обратите внимание: в большинстве программ [`isinstance()`](https://python-all.ru/3.3/library/functions.html#isinstance) для пользовательских классов используется нечасто. Если вы сами разрабатываете классы, более правильным объектно-ориентированным стилем будет определять в классах методы, инкапсулирующие определённое поведение, вместо проверки класса объекта и выполнения разных действий в зависимости от того, к какому классу он принадлежит. Например, если у вас есть функция, которая делает что-то:11061107```python1108def search(obj):1109    if isinstance(obj, Mailbox):1110        # ... код для поиска в почтовом ящике1111    elif isinstance(obj, Document):1112        # ... код для поиска в документе1113    elif ...1114```11151116Более правильный подход – определить метод `search()` во всех классах и просто вызывать его:11171118```python1119class Mailbox:1120    def search(self):1121        # ... код для поиска в почтовом ящике11221123class Document:1124    def search(self):1125        # ... код для поиска в документе11261127obj.search()1128```11291130### [Что такое делегирование?](https://python-all.ru/3.3/faq/programming.html#id54)11311132Делегирование – это объектно-ориентированный приём (также называемый шаблоном проектирования). Допустим, у вас есть объект `x`, и вы хотите изменить поведение только одного из его методов. Можно создать новый класс, который предоставляет новую реализацию интересующего вас метода, а все остальные методы делегирует соответствующим методам объекта `x`.11331134Программисты на Python могут легко реализовать делегирование. Например, следующий класс реализует класс, который ведёт себя как файл, но преобразует все записываемые данные в верхний регистр:11351136```python1137class UpperOut:11381139    def __init__(self, outfile):1140        self._outfile = outfile11411142    def write(self, s):1143        self._outfile.write(s.upper())11441145    def __getattr__(self, name):1146        return getattr(self._outfile, name)1147```11481149Здесь класс `UpperOut` переопределяет метод `write()`, чтобы преобразовывать строку аргумента в верхний регистр перед вызовом базового метода `self.__outfile.write()`. Все остальные методы делегируются базовому объекту `self.__outfile`. Делегирование осуществляется через метод `__getattr__`; обратитесь к [*ссылке на язык*](https://python-all.ru/3.3/reference/datamodel.html#attribute-access) для получения дополнительной информации об управлении доступом к атрибутам.11501151Обратите внимание: в более общих случаях делегирование может усложняться. Когда атрибуты необходимо не только получать, но и устанавливать, класс должен также определить метод [`__setattr__()`](https://python-all.ru/3.3/reference/datamodel.html#object.__setattr__), и делать это нужно аккуратно. Базовая реализация [`__setattr__()`](https://python-all.ru/3.3/reference/datamodel.html#object.__setattr__) примерно эквивалентна следующему:11521153```python1154class X:1155    ...1156    def __setattr__(self, name, value):1157        self.__dict__[name] = value1158    ...1159```11601161Большинство реализаций [`__setattr__()`](https://python-all.ru/3.3/reference/datamodel.html#object.__setattr__) должны изменять `self.__dict__` для хранения локального состояния self, чтобы не вызывать бесконечную рекурсию.11621163### [Как вызвать метод, определённый в базовом классе, из производного класса, который его переопределяет?](https://python-all.ru/3.3/faq/programming.html#id55)11641165Используйте встроенную функцию [`super()`](https://python-all.ru/3.3/library/functions.html#super):11661167```python1168class Derived(Base):1169    def meth (self):1170        super(Derived, self).meth()1171```11721173Для версий до 3.0 вы могли использовать классические классы. Для определения класса вида `class Derived(Base): ...` можно вызвать метод `meth()`, определённый в `Base` (или одном из базовых классов `Base`), как `Base.meth(self, аргументы...)`. Здесь `Base.meth` – это несвязанный метод, поэтому нужно передать аргумент `self`.11741175### [Как организовать код, чтобы было проще изменить базовый класс?](https://python-all.ru/3.3/faq/programming.html#id56)11761177Можно определить псевдоним для базового класса, присвоить ему реальный базовый класс до определения вашего класса и использовать псевдоним во всём классе. Тогда всё, что нужно изменить – это значение, присвоенное псевдониму. Кстати, этот трюк также удобен, если вы хотите динамически (например, в зависимости от доступности ресурсов) выбирать, какой базовый класс использовать. Пример:11781179```python1180BaseAlias = <real base class>11811182class Derived(BaseAlias):1183    def meth(self):1184        BaseAlias.meth(self)1185        ...1186```11871188### [Как создать статические данные класса и статические методы класса?](https://python-all.ru/3.3/faq/programming.html#id57)11891190В Python поддерживаются как статические данные, так и статические методы (в смысле C++ или Java).11911192Для статических данных просто определите атрибут класса. Чтобы присвоить атрибуту новое значение, необходимо явно указать имя класса в присваивании:11931194```python1195class C:1196    count = 0   # количество вызовов C.__init__11971198    def __init__(self):1199        C.count = C.count + 112001201    def getcount(self):1202        return C.count  # или вернуть self.count1203```12041205`c.count` также ссылается на `C.count` для любого `c`, для которого выполняется `isinstance(c, C)`, если только это не переопределено самим объектом `c` или каким-либо классом на пути поиска от `c.__class__` обратно к `C`.12061207Предупреждение: внутри метода C присваивание вида `self.count = 42` создаёт новый, не связанный экземпляр с именем «count» в собственном словаре `self`. Повторное связывание статического имени данных класса всегда должно указывать сам класс, независимо от того, находится ли оно внутри метода или нет:12081209```python1210C.count = 3141211```12121213Статические методы возможны:12141215```python1216class C:1217    @staticmethod1218    def static(arg1, arg2, arg3):1219        # Нет параметра 'self'!1220        ...1221```12221223Однако гораздо более прямолинейный способ получить эффект статического метода – это простая функция уровня модуля:12241225```python1226def getcount():1227    return C.count1228```12291230Если код организован так, что на каждый модуль определён один класс (или тесно связанная иерархия классов), это обеспечивает нужную инкапсуляцию.12311232### [Как перегрузить конструкторы (или методы) в Python?](https://python-all.ru/3.3/faq/programming.html#id58)12331234Этот ответ на самом деле применим ко всем методам, но вопрос обычно возникает в первую очередь в контексте конструкторов.12351236В C++ вы бы написали12371238```c1239class C {1240    C() { cout << "No arguments\n"; }1241    C(int i) { cout << "Argument is " << i << "\n"; }1242}1243```12441245В Python нужно написать один конструктор, который обрабатывает все случаи с помощью аргументов по умолчанию. Например:12461247```python1248class C:1249    def __init__(self, i=None):1250        if i is None:1251            print("No arguments")1252        else:1253            print("Argument is", i)1254```12551256Это не полностью эквивалентно, но на практике достаточно близко.12571258Можно также попробовать список аргументов переменной длины, например12591260```python1261def __init__(self, *args):1262    ...1263```12641265Тот же подход работает для всех определений методов.12661267### [Я пытаюсь использовать \_\_spam и получаю ошибку про \_SomeClassName\_\_spam.](https://python-all.ru/3.3/faq/programming.html#id59)12681269Имена переменных с двойным подчёркиванием в начале подвергаются «искажению», что даёт простой, но эффективный способ определения частных переменных класса. Любой идентификатор вида `__spam` (не менее двух ведущих подчёркиваний, не более одного завершающего) текстуально заменяется на `_classname__spam`, где `classname` – это имя текущего класса с удалёнными ведущими подчёркиваниями.12701271Это не гарантирует приватности: внешний пользователь всё равно может намеренно получить доступ к атрибуту «\_classname\_\_spam», а частные значения видны в `__dict__` объекта. Многие программисты Python вообще не утруждают себя использованием частных имён переменных.12721273### [Мой класс определяет \_\_del\_\_, но он не вызывается, когда я удаляю объект.](https://python-all.ru/3.3/faq/programming.html#id60)12741275Для этого есть несколько возможных причин.12761277Оператор [https://python-all.ru/3.3/reference/datamodel.html#object.__del__](https://python-all.ru/3.3/reference/datamodel.html#object.__del__)del не обязательно вызывает `__del__()` – он просто уменьшает счётчик ссылок объекта, и если тот достигает нуля, вызывается [`__del__()`](https://python-all.ru/3.3/reference/datamodel.html#object.__del__).12781279Если ваши структуры данных содержат циклические ссылки (например, дерево, где каждый потомок имеет ссылку на родителя, а каждый родитель – список потомков), счётчики ссылок никогда не обнулятся. Время от времени Python запускает алгоритм для обнаружения таких циклов, но сборщик мусора может запуститься спустя некоторое время после исчезновения последней ссылки на вашу структуру данных, поэтому ваш метод [`__del__()`](https://python-all.ru/3.3/reference/datamodel.html#object.__del__) может быть вызван в неудобный и случайный момент. Это неудобно, если вы пытаетесь воспроизвести проблему. Хуже того, порядок, в котором выполняются методы [`__del__()`](https://python-all.ru/3.3/reference/datamodel.html#object.__del__) объектов, произволен. Вы можете запустить [`gc.collect()`](https://python-all.ru/3.3/library/gc.html#gc.collect), чтобы принудительно выполнить сборку, но существуют *патологические* случаи, когда объекты никогда не будут собраны.12801281Несмотря на сборщик циклов, всё же стоит определять явный метод `close()` для объектов, который следует вызывать, когда объект больше не нужен. Метод `close()` может затем удалять атрибуты, ссылающиеся на подобъекты. Не вызывайте [`__del__()`](https://python-all.ru/3.3/reference/datamodel.html#object.__del__) напрямую – [`__del__()`](https://python-all.ru/3.3/reference/datamodel.html#object.__del__) должен вызывать `close()`, а `close()` должен гарантировать, что его можно вызвать для одного и того же объекта несколько раз.12821283Ещё один способ избежать циклических ссылок – использовать модуль [`weakref`](https://python-all.ru/3.3/library/weakref.html#module-weakref), который позволяет указывать на объекты без увеличения их счётчика ссылок. Например, в древовидных структурах данных для ссылок на родителя и соседей (если они нужны) следует использовать слабые ссылки.12841285Наконец, если ваш метод [`__del__()`](https://python-all.ru/3.3/reference/datamodel.html#object.__del__) вызывает исключение, в [`sys.stderr`](https://python-all.ru/3.3/library/sys.html#sys.stderr) выводится предупреждение.12861287### [Как получить список всех экземпляров данного класса?](https://python-all.ru/3.3/faq/programming.html#id61)12881289Python не отслеживает все экземпляры класса (или встроенного типа). Можно запрограммировать конструктор класса так, чтобы он отслеживал все экземпляры, сохраняя список слабых ссылок на каждый экземпляр.12901291### [Почему результат `id()` кажется неуникальным?](https://python-all.ru/3.3/faq/programming.html#id62)12921293Встроенная функция [`id()`](https://python-all.ru/3.3/library/functions.html#id) возвращает целое число, которое гарантированно будет уникальным на время жизни объекта. Поскольку в CPython это адрес памяти объекта, часто бывает, что после удаления объекта из памяти следующий только что созданный объект выделяется в той же позиции памяти. Это иллюстрируется следующим примером:12941295```python1296>>> id(1000)1297139012721298>>> id(2000)1299139012721300```13011302Два идентификатора принадлежат разным целочисленным объектам, которые создаются до вызова `id()` и сразу после него удаляются. Чтобы убедиться, что объекты, чьи идентификаторы вы хотите проверить, всё ещё существуют, создайте другую ссылку на объект:13031304```python1305>>> a = 1000; b = 20001306>>> id(a)1307139012721308>>> id(b)1309138912961310```13111312## [Модули](https://python-all.ru/3.3/faq/programming.html#id63)13131314### [Как создать .pyc-файл?](https://python-all.ru/3.3/faq/programming.html#id64)13151316Когда модуль импортируется впервые (или когда исходный файл изменился с момента создания текущего скомпилированного файла), в подкаталоге `__pycache__` каталога, содержащего файл `.py`, должен быть создан файл `.pyc` с скомпилированным кодом. Имя файла `.pyc` будет начинаться с того же имени, что и файл `.py`, и заканчиваться на `.pyc`, со средним компонентом, зависящим от конкретного двоичного файла `python`, который его создал. (Подробнее см. [**PEP 3147**](https://python-all.ru/3.3/faq/programming.html).)13171318Одна из причин, по которой файл `.pyc` может не создаваться, – проблема с правами доступа к каталогу, содержащему исходный файл, из-за чего не может быть создан подкаталог `__pycache__`. Это может произойти, например, если вы разрабатываете как один пользователь, а запускаете как другой, например, при тестировании с веб-сервером.13191320Если не установлена переменная окружения [`PYTHONDONTWRITEBYTECODE`](https://python-all.ru/3.3/using/cmdline.html#envvar-PYTHONDONTWRITEBYTECODE), создание файла .pyc происходит автоматически при импорте модуля, если у Python есть возможность (права доступа, свободное место и т.д.) создать подкаталог `__pycache__` и записать в него скомпилированный модуль.13211322Запуск Python для сценария верхнего уровня не считается импортом, и файл `.pyc` создан не будет. Например, если у вас есть модуль верхнего уровня `foo.py`, который импортирует другой модуль `xyz.py`, то при запуске `foo` (введя команду оболочки `python foo.py`) файл `.pyc` будет создан для `xyz`, поскольку `xyz` импортируется, но файл `.pyc` не будет создан для `foo`, так как `foo.py` не импортируется.13231324Если вам нужно создать файл `.pyc` для `foo` – то есть создать файл `.pyc` для модуля, который не импортируется, – это можно сделать с помощью модулей [`py_compile`](https://python-all.ru/3.3/library/py_compile.html#module-py_compile) и [`compileall`](https://python-all.ru/3.3/library/compileall.html#module-compileall).13251326Модуль [`py_compile`](https://python-all.ru/3.3/library/py_compile.html#module-py_compile) может вручную компилировать любой модуль. Один из способов – интерактивно использовать функцию `compile()` из этого модуля:13271328```python1329>>> import py_compile1330>>> py_compile.compile('foo.py')                 1331```13321333Это запишет `.pyc` в подкаталог `__pycache__` в том же месте, что и `foo.py` (или вы можете переопределить это с помощью необязательного параметра `cfile`).13341335Вы также можете автоматически скомпилировать все файлы в каталоге или каталогах, используя модуль [`compileall`](https://python-all.ru/3.3/library/compileall.html#module-compileall). Это можно сделать из командной строки, запустив `compileall.py` и указав путь к каталогу, содержащему файлы Python для компиляции:13361337```python1338python -m compileall .1339```13401341### [Как узнать имя текущего модуля?](https://python-all.ru/3.3/faq/programming.html#id65)13421343Модуль может узнать своё собственное имя, обратившись к предопределённой глобальной переменной `__name__`. Если она равна `'__main__'`, программа выполняется как сценарий. Многие модули, которые обычно используются путём импорта, также предоставляют интерфейс командной строки или самопроверку и выполняют этот код только после проверки `__name__`:13441345```python1346def main():1347    print('Running test...')1348    ...13491350if __name__ == '__main__':1351    main()1352```13531354### [Как сделать модули, которые импортируют друг друга?](https://python-all.ru/3.3/faq/programming.html#id66)13551356Предположим, у вас есть следующие модули:13571358foo.py:13591360```python1361from bar import bar_var1362foo_var = 11363```13641365bar.py:13661367```python1368from foo import foo_var1369bar_var = 21370```13711372Проблема в том, что интерпретатор выполнит следующие шаги:13731374- main импортирует foo1375- Создаются пустые глобальные переменные для foo1376- foo компилируется и начинает выполняться1377- foo импортирует bar1378- Создаются пустые глобальные переменные для bar1379- bar компилируется и начинает выполняться1380- bar импортирует foo (это пустая операция, так как модуль с именем foo уже существует)1381- bar.foo\_var = foo.foo\_var13821383Последний шаг завершается ошибкой, потому что Python ещё не закончил интерпретацию `foo`, и глобальный словарь символов для `foo` всё ещё пуст.13841385То же самое происходит при использовании `import foo` и последующей попытке обратиться к `foo.foo_var` в глобальном коде.13861387Существует (как минимум) три возможных обходных решения этой проблемы.13881389Гвидо ван Россум рекомендует избегать всех случаев использования `from <module> import ...` и размещать весь код внутри функций. Инициализации глобальных переменных и переменных класса должны использовать только константы или встроенные функции. Это означает, что всё из импортированного модуля указывается как `<module>.<name>`.13901391Джим Роскинд предлагает выполнять шаги в следующем порядке в каждом модуле:13921393- экспорт (глобальные переменные, функции и классы, которым не нужны импортированные базовые классы)1394- Операторы `import`1395- активный код (включая глобальные переменные, инициализируемые из импортированных значений).13961397ван Россуму такой подход не очень нравится, потому что импорты оказываются в странном месте, но это работает.13981399Маттиас Урлихс рекомендует перестроить код так, чтобы рекурсивный импорт вообще не требовался.14001401Эти решения не являются взаимоисключающими.14021403### [\_\_import\_\_(‘x.y.z’) возвращает \<module ‘x’\>; как получить z?](https://python-all.ru/3.3/faq/programming.html#id67)14041405Попробуйте:14061407```python1408__import__('x.y.z').y.z1409```14101411В более реалистичных ситуациях, возможно, придётся сделать что-то вроде14121413```python1414m = __import__(s)1415for i in s.split(".")[1:]:1416    m = getattr(m, i)1417```14181419См. [`importlib`](https://python-all.ru/3.3/library/importlib.html#module-importlib) для удобной функции [`import_module()`](https://python-all.ru/3.3/library/importlib.html#importlib.import_module).14201421### [Когда я редактирую импортированный модуль и повторно импортирую его, изменения не отображаются. Почему это происходит?](https://python-all.ru/3.3/faq/programming.html#id68)14221423Из соображений эффективности и согласованности Python читает файл модуля только при первом импорте модуля. Если бы это было не так, в программе, состоящей из многих модулей, каждый из которых импортирует один и тот же базовый модуль, базовый модуль разбирался бы и переразбирался многократно. Чтобы принудительно перечитать изменённый модуль, сделайте следующее:14241425```python1426import imp1427import modname1428imp.reload(modname)1429```14301431Предупреждение: этот метод не является абсолютно надёжным. В частности, модули, содержащие операторы типа14321433```python1434from modname import some_objects1435```14361437будут продолжать работать со старой версией импортированных объектов. Если модуль содержит определения классов, существующие экземпляры классов *не* будут обновлены для использования нового определения класса. Это может привести к следующему парадоксальному поведению:14381439```python1440>>> import imp1441>>> import cls1442>>> c = cls.C()                # Создать экземпляр C1443>>> imp.reload(cls)1444<module 'cls' from 'cls.py'>1445>>> isinstance(c, cls.C)       # isinstance ложно?!?1446False1447```14481449Суть проблемы становится ясна, если вывести «идентичность» объектов классов:14501451```python1452>>> hex(id(c.__class__))1453'0x7352a0'1454>>> hex(id(cls.C))1455'0x4198d0'1456```1457