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

programming.md

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

1> **Источник:** https://python-all.ru/3.7/faq/programming.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# [ЧЗВ по программированию](https://python-all.ru/3.7/faq/programming.html#id1)89Содержание1011- [Вопросы по программированию](https://python-all.ru/3.7/faq/programming.html#programming-faq)1213  - [Общие вопросы](https://python-all.ru/3.7/faq/programming.html#general-questions)1415    - [Существует ли отладчик на уровне исходного кода с точками останова, пошаговым выполнением и т. д.?](https://python-all.ru/3.7/faq/programming.html#is-there-a-source-code-level-debugger-with-breakpoints-single-stepping-etc)16    - [Существует ли инструмент для поиска ошибок или выполнения статического анализа?](https://python-all.ru/3.7/faq/programming.html#is-there-a-tool-to-help-find-bugs-or-perform-static-analysis)17    - [Как создать автономный исполняемый файл из скрипта Python?](https://python-all.ru/3.7/faq/programming.html#how-can-i-create-a-stand-alone-binary-from-a-python-script)18    - [Существуют ли стандарты кодирования или руководство по стилю для программ на Python?](https://python-all.ru/3.7/faq/programming.html#are-there-coding-standards-or-a-style-guide-for-python-programs)19  - [Ядро языка](https://python-all.ru/3.7/faq/programming.html#core-language)2021    - [Почему возникает UnboundLocalError, если переменная имеет значение?](https://python-all.ru/3.7/faq/programming.html#why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value)22    - [Каковы правила для локальных и глобальных переменных в Python?](https://python-all.ru/3.7/faq/programming.html#what-are-the-rules-for-local-and-global-variables-in-python)23    - [Почему лямбда-функции, определённые в цикле с разными значениями, возвращают один и тот же результат?](https://python-all.ru/3.7/faq/programming.html#why-do-lambdas-defined-in-a-loop-with-different-values-all-return-the-same-result)24    - [Как разделять глобальные переменные между модулями?](https://python-all.ru/3.7/faq/programming.html#how-do-i-share-global-variables-across-modules)25    - [Каковы «лучшие практики» использования import в модуле?](https://python-all.ru/3.7/faq/programming.html#what-are-the-best-practices-for-using-import-in-a-module)26    - [Почему значения по умолчанию разделяются между объектами?](https://python-all.ru/3.7/faq/programming.html#why-are-default-values-shared-between-objects)27    - [Как передать необязательные или именованные параметры из одной функции в другую?](https://python-all.ru/3.7/faq/programming.html#how-can-i-pass-optional-or-keyword-parameters-from-one-function-to-another)28    - [В чём разница между аргументами и параметрами?](https://python-all.ru/3.7/faq/programming.html#what-is-the-difference-between-arguments-and-parameters)29    - [Почему изменение списка 'y' также изменило список 'x'?](https://python-all.ru/3.7/faq/programming.html#why-did-changing-list-y-also-change-list-x)30    - [Как написать функцию с выходными параметрами (передача по ссылке)?](https://python-all.ru/3.7/faq/programming.html#how-do-i-write-a-function-with-output-parameters-call-by-reference)31    - [Как создать функцию высшего порядка в Python?](https://python-all.ru/3.7/faq/programming.html#how-do-you-make-a-higher-order-function-in-python)32    - [Как скопировать объект в Python?](https://python-all.ru/3.7/faq/programming.html#how-do-i-copy-an-object-in-python)33    - [Как найти методы или атрибуты объекта?](https://python-all.ru/3.7/faq/programming.html#how-can-i-find-the-methods-or-attributes-of-an-object)34    - [Как моему коду узнать имя объекта?](https://python-all.ru/3.7/faq/programming.html#how-can-my-code-discover-the-name-of-an-object)35    - [Что не так с приоритетом оператора запятой?](https://python-all.ru/3.7/faq/programming.html#what-s-up-with-the-comma-operator-s-precedence)36    - [Существует ли эквивалент тернарного оператора «?:» из C?](https://python-all.ru/3.7/faq/programming.html#is-there-an-equivalent-of-c-s-ternary-operator)37    - [Можно ли писать запутанные однострочники на Python?](https://python-all.ru/3.7/faq/programming.html#is-it-possible-to-write-obfuscated-one-liners-in-python)38    - [Что означает косая черта (/) в списке параметров функции?](https://python-all.ru/3.7/faq/programming.html#what-does-the-slash-in-the-parameter-list-of-a-function-mean)39  - [Числа и строки](https://python-all.ru/3.7/faq/programming.html#numbers-and-strings)4041    - [Как указать шестнадцатеричные и восьмеричные целые числа?](https://python-all.ru/3.7/faq/programming.html#how-do-i-specify-hexadecimal-and-octal-integers)42    - [Почему -22 // 10 возвращает -3?](https://python-all.ru/3.7/faq/programming.html#why-does-22-10-return-3)43    - [Как преобразовать строку в число?](https://python-all.ru/3.7/faq/programming.html#how-do-i-convert-a-string-to-a-number)44    - [Как преобразовать число в строку?](https://python-all.ru/3.7/faq/programming.html#how-do-i-convert-a-number-to-a-string)45    - [Как изменить строку на месте?](https://python-all.ru/3.7/faq/programming.html#how-do-i-modify-a-string-in-place)46    - [Как с помощью строк вызывать функции и методы?](https://python-all.ru/3.7/faq/programming.html#how-do-i-use-strings-to-call-functions-methods)47    - [Существует ли аналог функции chomp() из Perl для удаления завершающих символов новой строки из строк?](https://python-all.ru/3.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/3.7/faq/programming.html#is-there-a-scanf-or-sscanf-equivalent)49    - [Что означает ошибка UnicodeDecodeError или UnicodeEncodeError?](https://python-all.ru/3.7/faq/programming.html#what-does-unicodedecodeerror-or-unicodeencodeerror-error-mean)50  - [Производительность](https://python-all.ru/3.7/faq/programming.html#performance)5152    - [Моя программа слишком медленная. Как её ускорить?](https://python-all.ru/3.7/faq/programming.html#my-program-is-too-slow-how-do-i-speed-it-up)53    - [Какой способ конкатенации множества строк самый эффективный?](https://python-all.ru/3.7/faq/programming.html#what-is-the-most-efficient-way-to-concatenate-many-strings-together)54  - [Последовательности (кортежи/списки)](https://python-all.ru/3.7/faq/programming.html#sequences-tuples-lists)5556    - [Как преобразовывать кортежи в списки и обратно?](https://python-all.ru/3.7/faq/programming.html#how-do-i-convert-between-tuples-and-lists)57    - [Что такое отрицательный индекс?](https://python-all.ru/3.7/faq/programming.html#what-s-a-negative-index)58    - [Как перебрать последовательность в обратном порядке?](https://python-all.ru/3.7/faq/programming.html#how-do-i-iterate-over-a-sequence-in-reverse-order)59    - [Как удалить дубликаты из списка?](https://python-all.ru/3.7/faq/programming.html#how-do-you-remove-duplicates-from-a-list)60    - [Как создать массив в Python?](https://python-all.ru/3.7/faq/programming.html#how-do-you-make-an-array-in-python)61    - [Как создать многомерный список?](https://python-all.ru/3.7/faq/programming.html#how-do-i-create-a-multidimensional-list)62    - [Как применить метод к последовательности объектов?](https://python-all.ru/3.7/faq/programming.html#how-do-i-apply-a-method-to-a-sequence-of-objects)63    - [Почему a\_tuple\[i\] += \[‘item’\] вызывает исключение, хотя само сложение работает?](https://python-all.ru/3.7/faq/programming.html#why-does-a-tuple-i-item-raise-an-exception-when-the-addition-works)64    - [Я хочу выполнить сложную сортировку: можно ли в Python реализовать преобразование Шварца?](https://python-all.ru/3.7/faq/programming.html#i-want-to-do-a-complicated-sort-can-you-do-a-schwartzian-transform-in-python)65    - [Как отсортировать один список по значениям из другого списка?](https://python-all.ru/3.7/faq/programming.html#how-can-i-sort-one-list-by-values-from-another-list)66  - [Объекты](https://python-all.ru/3.7/faq/programming.html#objects)6768    - [Что такое класс?](https://python-all.ru/3.7/faq/programming.html#what-is-a-class)69    - [Что такое метод?](https://python-all.ru/3.7/faq/programming.html#what-is-a-method)70    - [Что такое self?](https://python-all.ru/3.7/faq/programming.html#what-is-self)71    - [Как проверить, является ли объект экземпляром данного класса или его подкласса?](https://python-all.ru/3.7/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.7/faq/programming.html#what-is-delegation)73    - [Как вызвать метод, определённый в базовом классе, из производного класса, который его переопределяет?](https://python-all.ru/3.7/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.7/faq/programming.html#how-can-i-organize-my-code-to-make-it-easier-to-change-the-base-class)75    - [Как создать статические данные класса и статические методы класса?](https://python-all.ru/3.7/faq/programming.html#how-do-i-create-static-class-data-and-static-class-methods)76    - [Как перегрузить конструкторы (или методы) в Python?](https://python-all.ru/3.7/faq/programming.html#how-can-i-overload-constructors-or-methods-in-python)77    - [Я пытаюсь использовать \_\_spam и получаю ошибку о \_SomeClassName\_\_spam.](https://python-all.ru/3.7/faq/programming.html#i-try-to-use-spam-and-i-get-an-error-about-someclassname-spam)78    - [Мой класс определяет \_\_del\_\_, но он не вызывается при удалении объекта.](https://python-all.ru/3.7/faq/programming.html#my-class-defines-del-but-it-is-not-called-when-i-delete-the-object)79    - [Как получить список всех экземпляров данного класса?](https://python-all.ru/3.7/faq/programming.html#how-do-i-get-a-list-of-all-instances-of-a-given-class)80    - [Почему результат `id()` не является уникальным?](https://python-all.ru/3.7/faq/programming.html#why-does-the-result-of-id-appear-to-be-not-unique)81  - [Модули](https://python-all.ru/3.7/faq/programming.html#modules)8283    - [Как создать .pyc-файл?](https://python-all.ru/3.7/faq/programming.html#how-do-i-create-a-pyc-file)84    - [Как узнать имя текущего модуля?](https://python-all.ru/3.7/faq/programming.html#how-do-i-find-the-current-module-name)85    - [Как сделать так, чтобы модули импортировали друг друга?](https://python-all.ru/3.7/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.7/faq/programming.html#import-x-y-z-returns-module-x-how-do-i-get-z)87    - [При редактировании импортированного модуля и его повторном импорте изменения не отображаются. Почему это происходит?](https://python-all.ru/3.7/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.7/faq/programming.html#id2)9091### [Существует ли отладчик на уровне исходного кода с точками останова, пошаговым выполнением и т. д.?](https://python-all.ru/3.7/faq/programming.html#id3)9293Да.9495Ниже описано несколько отладчиков для Python, а встроенная функция [`breakpoint()`](https://python-all.ru/3.7/library/functions.html#breakpoint) позволяет войти в любой из них.9697Модуль pdb – это простой, но достаточный консольный отладчик для Python. Он является частью стандартной библиотеки Python и [`documented in the Library Reference Manual`](https://python-all.ru/3.7/library/pdb.html#module-pdb). Вы также можете написать собственный отладчик, используя код pdb в качестве примера.9899Интерактивная среда разработки IDLE, которая входит в стандартную установку Python (обычно доступна как Tools/scripts/idle), включает графический отладчик.100101PythonWin – это IDE для Python, включающая графический отладчик на основе pdb. Отладчик Pythonwin подсвечивает точки останова и обладает рядом полезных возможностей, таких как отладка программ, не относящихся к Pythonwin. PythonWin доступен как часть проекта [Python for Windows Extensions](https://python-all.ru/3.7/faq/programming.html) и как часть дистрибутива ActivePython (см. [https://www.activestate.com/activepython](https://python-all.ru/3.7/faq/programming.html)).102103[Boa Constructor](https://python-all.ru/3.7/faq/programming.html) – это среда разработки и конструктор графического интерфейса на основе wxWidgets. Он предоставляет визуальное создание и редактирование фреймов, инспектор объектов, различные представления исходного кода, включая обозреватели объектов, иерархии наследования, HTML-документацию, сгенерированную из строк документации, расширенный отладчик, встроенную справку и поддержку Zope.104105[Eric](https://python-all.ru/3.7/faq/programming.html) – это IDE, построенная на PyQt и компоненте редактирования Scintilla.106107Pydb – это версия стандартного отладчика Python pdb, модифицированная для использования с DDD (Data Display Debugger), популярным графическим интерфейсом отладчика. Pydb можно найти по адресу [http://bashdb.sourceforge.net/pydb/](https://python-all.ru/3.7/faq/programming.html), а DDD – по адресу [https://www.gnu.org/software/ddd](https://python-all.ru/3.7/faq/programming.html).108109Существует ряд коммерческих IDE для Python, включающих графические отладчики. Среди них:110111- Wing IDE ([https://wingware.com/](https://python-all.ru/3.7/faq/programming.html))112- Komodo IDE ([https://komodoide.com/](https://python-all.ru/3.7/faq/programming.html))113- PyCharm ([https://www.jetbrains.com/pycharm/](https://python-all.ru/3.7/faq/programming.html))114115### [Существует ли инструмент для поиска ошибок или выполнения статического анализа?](https://python-all.ru/3.7/faq/programming.html#id4)116117Да.118119PyChecker – это инструмент статического анализа, который находит ошибки в исходном коде Python и предупреждает о сложности и стиле кода. PyChecker можно получить по адресу [http://pychecker.sourceforge.net/](https://python-all.ru/3.7/faq/programming.html).120121[Pylint](https://python-all.ru/3.7/faq/programming.html) – это ещё один инструмент, который проверяет, соответствует ли модуль стандарту кодирования, а также позволяет писать плагины для добавления собственных возможностей. В дополнение к проверке ошибок, выполняемой PyChecker, Pylint предлагает некоторые дополнительные функции, такие как проверка длины строк, соответствие имён переменных вашему стандарту кодирования, полная реализация объявленных интерфейсов и многое другое. На [https://docs.pylint.org/](https://python-all.ru/3.7/faq/programming.html) представлен полный список возможностей Pylint.122123Статические анализаторы типов, такие как [Mypy](https://python-all.ru/3.7/faq/programming.html), [Pyre](https://python-all.ru/3.7/faq/programming.html) и [Pytype](https://python-all.ru/3.7/faq/programming.html), могут проверять аннотации типов в исходном коде Python.124125### [Как создать автономный исполняемый файл из скрипта Python?](https://python-all.ru/3.7/faq/programming.html#id5)126127Вам не нужно уметь компилировать Python в C, если ваша цель – создать автономную программу, которую пользователи могут скачать и запустить без предварительной установки дистрибутива Python. Существует ряд инструментов, которые определяют набор модулей, необходимых программе, и связывают эти модули вместе с бинарным файлом Python, создавая единый исполняемый файл.128129Один из способов – использовать инструмент freeze, который включён в дерево исходных текстов Python как `Tools/freeze`. Он преобразует байт-код Python в C-массивы; с помощью C-компилятора можно встроить все свои модули в новую программу, которая затем компонуется со стандартными модулями Python.130131Он работает, рекурсивно сканируя ваш исходный код на наличие операторов import (в обеих формах) и ищет модули в стандартном пути Python, а также в каталоге исходного кода (для встроенных модулей). Затем он превращает байт-код модулей, написанных на Python, в код C (инициализаторы массивов, которые можно превратить в объекты кода с помощью модуля marshal) и создает специальный конфигурационный файл, содержащий только те встроенные модули, которые действительно используются в программе. После этого он компилирует сгенерированный код C и компонует его с остальной частью интерпретатора Python, формируя самодостаточный бинарный файл, который ведет себя точно так же, как ваш скрипт.132133Очевидно, freeze требует компилятор C. Существует несколько других утилит, которые не требуют. Одна из них – py2exe Томаса Хеллера (только для Windows) по адресу134135> [http://www.py2exe.org/](https://python-all.ru/3.7/faq/programming.html)136137Другой инструмент – [cx\_Freeze](https://python-all.ru/3.7/faq/programming.html) Энтони Туйнинги.138139### [Существуют ли стандарты кодирования или руководство по стилю для программ на Python?](https://python-all.ru/3.7/faq/programming.html#id6)140141Да. Требуемый стиль оформления кода для модулей стандартной библиотеки описан в документе [**PEP 8**](https://python-all.ru/3.7/faq/programming.html).142143## [Ядро языка](https://python-all.ru/3.7/faq/programming.html#id7)144145### [Почему возникает UnboundLocalError, если переменная содержит значение?](https://python-all.ru/3.7/faq/programming.html#id8)146147Может быть неожиданным получить ошибку UnboundLocalError в ранее работавшем коде после добавления оператора присваивания где-то в теле функции.148149Этот код:150151```python152>>> x = 10153>>> def bar():154...     print(x)155>>> bar()15610157```158159работает, но этот код:160161```python162>>> x = 10163>>> def foo():164...     print(x)165...     x += 1166```167168приводит к ошибке UnboundLocalError:169170```python171>>> foo()172Traceback (most recent call last):173  ...174UnboundLocalError: local variable 'x' referenced before assignment175```176177Это происходит потому, что при присваивании значения переменной в некоторой области видимости эта переменная становится локальной для данной области и затеняет любую одноимённую переменную из внешней области. Поскольку последний оператор в foo присваивает новое значение `x`, компилятор считает её локальной переменной. Следовательно, когда предыдущий `print(x)` пытается вывести на печать неинициализированную локальную переменную, возникает ошибка.178179В приведённом выше примере можно получить доступ к переменной внешней области, объявив её глобальной:180181```python182>>> x = 10183>>> def foobar():184...     global x185...     print(x)186...     x += 1187>>> foobar()18810189```190191Такое явное объявление необходимо, чтобы напомнить: в отличие от внешне похожей ситуации с переменными класса и экземпляра, здесь фактически изменяется значение переменной во внешней области видимости:192193```python194>>> print(x)19511196```197198Аналогичное действие можно выполнить во вложенной области видимости с помощью ключевого слова [`nonlocal`](https://python-all.ru/3.7/reference/simple_stmts.html#nonlocal):199200```python201>>> def foo():202...    x = 10203...    def bar():204...        nonlocal x205...        print(x)206...        x += 1207...    bar()208...    print(x)209>>> foo()2101021111212```213214### [Каковы правила использования локальных и глобальных переменных в Python?](https://python-all.ru/3.7/faq/programming.html#id9)215216В Python переменные, на которые только ссылаются внутри функции, неявно считаются глобальными. Если переменной присваивается значение где-либо в теле функции, она считается локальной, если явно не объявлена как global.217218Хотя поначалу это может показаться удивительным, небольшое размышление объясняет такое поведение. С одной стороны, требование [`global`](https://python-all.ru/3.7/reference/simple_stmts.html#global) для присваиваемых переменных служит барьером против непреднамеренных побочных эффектов. С другой стороны, если бы `global` требовалось для всех глобальных ссылок, пришлось бы постоянно использовать `global`. Пришлось бы объявлять как global каждую ссылку на встроенную функцию или компонент импортированного модуля. Такая избыточность свела бы на нет пользу объявления `global` для выявления побочных эффектов.219220### [Почему лямбды, определённые в цикле с разными значениями, все возвращают один и тот же результат?](https://python-all.ru/3.7/faq/programming.html#id10)221222Предположим, что с помощью цикла for определяется несколько разных лямбд (или даже обычных функций), например:223224```python225>>> squares = []226>>> for x in range(5):227...     squares.append(lambda: x**2)228```229230Это даёт список, содержащий 5 лямбд, вычисляющих `x**2`. Можно ожидать, что при вызове они вернут соответственно `0`, `1`, `4`, `9` и `16`. Однако при попытке вызова обнаружится, что все они возвращают `16`:231232```python233>>> squares[2]()23416235>>> squares[4]()23616237```238239Это происходит потому, что `x` не является локальной для лямбд, а определена во внешней области видимости, и обращение к ней происходит при вызове лямбды, а не при её определении. В конце цикла значение `x` равно `4`, поэтому все функции теперь возвращают `4**2`, то есть `16`. Это можно также проверить, изменив значение `x` и посмотрев, как изменятся результаты лямбд:240241```python242>>> x = 8243>>> squares[2]()24464245```246247Чтобы избежать этого, необходимо сохранить значения в переменных, локальных для лямбд, чтобы они не зависели от значения глобальной `x`:248249```python250>>> squares = []251>>> for x in range(5):252...     squares.append(lambda n=x: n**2)253```254255Здесь `n=x` создаёт новую переменную `n`, локальную для лямбды и вычисляемую при её определении, так что она имеет то же значение, которое `x` имела в этот момент в цикле. Это означает, что значение `n` будет равно `0` в первой лямбде, `1` – во второй, `2` – в третьей и так далее. Следовательно, теперь каждая лямбда будет возвращать правильный результат:256257```python258>>> squares[2]()2594260>>> squares[4]()26116262```263264Обратите внимание: такое поведение присуще не только лямбдам, но и обычным функциям.265266### [Как разделять глобальные переменные между модулями?](https://python-all.ru/3.7/faq/programming.html#id11)267268Общепринятый способ обмена информацией между модулями в рамках одной программы – создать специальный модуль (часто называемый config или cfg). Достаточно импортировать модуль config во все модули приложения, и он станет доступен как глобальное имя. Поскольку у каждого модуля существует только один экземпляр, любые изменения объекта модуля отражаются везде. Например:269270config.py:271272```python273x = 0   # Значение по умолчанию для параметра конфигурации 'x'274```275276mod.py:277278```python279import config280config.x = 1281```282283main.py:284285```python286import config287import mod288print(config.x)289```290291Обратите внимание: использование модуля также является основой для реализации паттерна Singleton по той же причине.292293### [Каковы «лучшие практики» использования import в модуле?](https://python-all.ru/3.7/faq/programming.html#id12)294295В целом не стоит использовать `from modulename import *`. Это захламляет пространство имён импортёра и сильно усложняет линтерам обнаружение неопределённых имён.296297Импортируйте модули в начале файла. Так сразу становится ясно, какие ещё модули требуются вашему коду, и не возникает вопросов, находится ли имя модуля в области видимости. Использование одного импорта на строку упрощает добавление и удаление импортов, а использование нескольких импортов в одной строке экономит место на экране.298299Рекомендуется импортировать модули в следующем порядке:3003011. модули стандартной библиотеки – например `sys`, `os`, `getopt`, `re`3022. модули сторонних библиотек (всё, установленное в каталог site-packages Python), например mx.DateTime, ZODB, PIL.Image и т.д.3033. модули локальной разработки304305Иногда импорты приходится переносить внутрь функции или класса, чтобы избежать проблем с циклическими импортами. Gordon McMillan говорит:306307> Циклические импорты нормально работают, когда оба модуля используют форму импорта “import \<module\>”. Они перестают работать, когда второй модуль пытается получить имя из первого (“from module import name”), и импорт находится на верхнем уровне. Это происходит потому, что имена в первом модуле ещё недоступны, так как первый модуль занят импортом второго.308309В этом случае, если второй модуль используется только в одной функции, импорт можно легко перенести в эту функцию. К моменту вызова импорта первый модуль уже завершит инициализацию, и второй модуль сможет выполнить свой импорт.310311Также может потребоваться перенести импорты из верхнего уровня кода, если некоторые модули являются платформозависимыми. В таком случае может быть невозможно импортировать все модули в начале файла. Тогда хорошим решением будет импортировать нужные модули в соответствующем платформозависимом коде.312313Переносите импорты в локальную область видимости, например в определение функции, только если это необходимо для решения проблемы – избежания циклического импорта или сокращения времени инициализации модуля. Этот приём особенно полезен, когда многие импорты не нужны в зависимости от того, как выполняется программа. Также можно перенести импорты в функцию, если модули используются только в ней. Обратите внимание: первая загрузка модуля может быть дорогой из-за однократной инициализации, но повторные загрузки практически бесплатны и требуют лишь пары словарных поисков. Даже если имя модуля вышло из области видимости, сам модуль, скорее всего, доступен в [`sys.modules`](https://python-all.ru/3.7/library/sys.html#sys.modules).314315### [Почему значения по умолчанию являются общими для объектов?](https://python-all.ru/3.7/faq/programming.html#id13)316317Подобная ошибка часто подстерегает начинающих программистов. Рассмотрим следующую функцию:318319```python320def foo(mydict={}):  # Опасность: общая ссылка на один словарь для всех вызовов321    ... compute something ...322    mydict[key] = value323    return mydict324```325326При первом вызове этой функции `mydict` содержит один элемент. При втором вызове `mydict` содержит уже два элемента, потому что когда `foo()` начинает выполняться, `mydict` уже содержит один элемент.327328Часто ожидается, что при вызове функции для значений по умолчанию создаются новые объекты. Но это не так. Значения по умолчанию создаются ровно один раз, при определении функции. Если этот объект изменяется (как словарь в данном примере), то последующие вызовы функции будут обращаться к этому изменённому объекту.329330По определению, неизменяемые объекты – числа, строки, кортежи и `None` – защищены от изменений. Изменения изменяемых объектов, таких как словари, списки и экземпляры классов, могут приводить к путанице.331332Из-за этой особенности рекомендуется не использовать изменяемые объекты в качестве значений по умолчанию. Вместо этого используйте `None` в качестве значения по умолчанию, а внутри функции проверяйте, равен ли параметр `None`, и при необходимости создавайте новый список, словарь и т.д. Например, не пишите:333334```python335def foo(mydict={}):336    ...337```338339а:340341```python342def foo(mydict=None):343    if mydict is None:344        mydict = {}  # создать новый словарь для локального пространства имён345```346347Эта возможность может быть полезной. Если есть функция, вычисление которой требует много времени, распространённый приём – кэшировать параметры и результат каждого вызова функции, а при повторном запросе тех же значений возвращать сохранённый результат. Это называется «мемоизация» и может быть реализовано так:348349```python350# Вызывающие могут передавать только два параметра и опционально _cache по ключевому слову351def expensive(arg1, arg2, *, _cache={}):352    if (arg1, arg2) in _cache:353        return _cache[(arg1, arg2)]354355    # Вычислить значение356    result = ... expensive computation ...357    _cache[(arg1, arg2)] = result           # Сохранить результат в кеше358    return result359```360361Вместо значения по умолчанию можно использовать глобальную переменную со словарём; это дело вкуса.362363### [Как передать необязательные или именованные параметры из одной функции в другую?](https://python-all.ru/3.7/faq/programming.html#id14)364365Соберите аргументы с помощью спецификаторов `*` и `**` в списке параметров функции; это даст позиционные аргументы в виде кортежа, а именованные – в виде словаря. Затем вы можете передать эти аргументы при вызове другой функции, используя `*` и `**`:366367```python368def f(x, *args, **kwargs):369    ...370    kwargs['width'] = '14.3c'371    ...372    g(x, *args, **kwargs)373```374375### [В чём разница между аргументами и параметрами?](https://python-all.ru/3.7/faq/programming.html#id15)376377[Параметры](https://python-all.ru/3.7/glossary.html#term-parameter) определяются именами, которые указаны в определении функции, тогда как [аргументы](https://python-all.ru/3.7/glossary.html#term-argument) – это значения, которые передаются функции при её вызове. Параметры определяют, какие типы аргументов может принимать функция. Например, для такого определения функции:378379```python380def func(foo, bar=None, **kwargs):381    pass382```383384*foo*, *bar* и *kwargs* являются параметрами функции `func`. Однако при вызове `func`, например:385386```python387func(42, bar=314, extra=somevar)388```389390значения `42`, `314` и `somevar` являются аргументами.391392### [Почему изменение списка ‘y’ также изменило список ‘x’?](https://python-all.ru/3.7/faq/programming.html#id16)393394Если вы написали такой код:395396```python397>>> x = []398>>> y = x399>>> y.append(10)400>>> y401[10]402>>> x403[10]404```405406вас может интересовать, почему добавление элемента к `y` изменило и `x`.407408К этому результату приводят два фактора:4094101. Переменные – это просто имена, ссылающиеся на объекты. Операция `y = x` не создаёт копию списка – она создаёт новую переменную `y`, которая ссылается на тот же объект, что и `x`. Это означает, что существует только один объект (список), и обе переменные `x` и `y` ссылаются на него.4112. Списки являются [изменяемыми](https://python-all.ru/3.7/glossary.html#term-mutable), то есть их содержимое можно изменять.412413После вызова `append()` содержимое изменяемого объекта\\nизменилось с `[]` на `[10]`. Поскольку обе переменные ссылаются на один и тот же объект, использование любого имени даёт доступ к изменённому значению `[10]`.414415Если же присвоить неизменяемый объект `x`:416417```python418>>> x = 5  # int – неизменяемый тип419>>> y = x420>>> x = x + 1  # 5 нельзя изменить, здесь создаётся новый объект421>>> x4226423>>> y4245425```426427в этом случае `x` и `y` уже не равны. Это\\nпотому, что целые числа [неизменяемы](https://python-all.ru/3.7/glossary.html#term-immutable), и когда мы делаем `x = x + 1`, мы не\\nизменяем int `5`, увеличивая его значение; вместо этого мы создаём\\nновый объект (int `6`) и присваиваем его `x` (то есть изменяем, на какой объект ссылается `x`). После этого присваивания у нас есть два объекта (int `6` и `5`) и две переменные, ссылающиеся на них (`x` теперь ссылается на `6`, а `y` всё ещё ссылается на `5`).428429Некоторые операции (например `y.append(10)` и `y.sort()`) изменяют\\nобъект, тогда как внешне похожие операции (например `y = y + [10]`\\nи `sorted(y)`) создают новый объект. В общем случае в Python (и во всех случаях\\nв стандартной библиотеке) метод, изменяющий объект, возвращает `None`,\\nчтобы избежать путаницы между двумя типами операций. Так что если вы\\nошибочно напишете `y.sort()`, думая, что получите отсортированную копию `y`,\\nто вместо этого получите `None`, что, скорее всего, приведёт к легко диагностируемой ошибке в вашей программе.430431Однако есть один класс операций, где одна и та же операция иногда\\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новые объекты).432433Иными словами:434435- Если у нас есть изменяемый объект ([`list`](https://python-all.ru/3.7/library/stdtypes.html#list), [`dict`](https://python-all.ru/3.7/library/stdtypes.html#dict), [`set`](https://python-all.ru/3.7/library/stdtypes.html#set), и т. д.), можно использовать некоторые специфические операции для его изменения, и все переменные, которые на него ссылаются, увидят это изменение.436- Если у нас есть неизменяемый объект ([`str`](https://python-all.ru/3.7/library/stdtypes.html#str), [`int`](https://python-all.ru/3.7/library/functions.html#int), [`tuple`](https://python-all.ru/3.7/library/stdtypes.html#tuple), и т. д.), все переменные, которые на него ссылаются, всегда будут видеть одно и то же значение, но операции, преобразующие это значение в новое, всегда возвращают новый объект.437438Чтобы узнать, ссылаются ли две переменные на один и тот же объект, можно\\nиспользовать оператор [`is`](https://python-all.ru/3.7/reference/expressions.html#is) или встроенную функцию [`id()`](https://python-all.ru/3.7/library/functions.html#id).439440### [Как написать функцию с выходными параметрами (передача по ссылке)?](https://python-all.ru/3.7/faq/programming.html#id17)441442Помните, что в Python аргументы передаются по присваиванию. Поскольку присваивание лишь создает ссылки на объекты, между именем аргумента в вызывающей и вызываемой функции нет псевдонима, а значит, нет и передачи по ссылке как таковой. Желаемого эффекта можно достичь несколькими способами.4434441. Возвращая кортеж результатов:445446   ```python447   def func2(a, b):448       a = 'new-value'        # a и b – локальные имена449       b = b + 1              # присвоены новым объектам450       return a, b            # вернуть новые значения451452   x, y = 'old-value', 99453   x, y = func2(x, y)454   print(x, y)                # вывод: new-value 100455   ```456457   Это почти всегда самое понятное решение.4582. С помощью глобальных переменных. Это не потокобезопасно и не рекомендуется.4593. Передавая изменяемый (изменяемый на месте) объект:460461   ```python462   def func1(a):463       a[0] = 'new-value'     # 'a' ссылается на изменяемый список464       a[1] = a[1] + 1        # изменяет общий объект465466   args = ['old-value', 99]467   func1(args)468   print(args[0], args[1])    # вывод: new-value 100469   ```4704. Передавая словарь, который будет изменён:471472   ```python473   def func3(args):474       args['a'] = 'new-value'     # args – изменяемый словарь475       args['b'] = args['b'] + 1   # изменить его на месте476477   args = {'a': 'old-value', 'b': 99}478   func3(args)479   print(args['a'], args['b'])480   ```4815. Или объединив значения в экземпляре класса:482483   ```python484   class callByRef:485       def __init__(self, **args):486           for (key, value) in args.items():487               setattr(self, key, value)488489   def func4(args):490       args.a = 'new-value'        # args – изменяемый callByRef491       args.b = args.b + 1         # изменить объект на месте492493   args = callByRef(a='old-value', b=99)494   func4(args)495   print(args.a, args.b)496   ```497498   Почти никогда нет веской причины усложнять до такой степени.499500Лучший выбор – вернуть кортеж, содержащий несколько результатов.501502### [Как сделать функцию высшего порядка в Python?](https://python-all.ru/3.7/faq/programming.html#id18)503504У вас есть два варианта: использовать вложенные области видимости или вызываемые объекты.\\nНапример, предположим, вы хотите определить `linear(a,b)`, которая возвращает\\nфункцию `f(x)`, вычисляющую значение `a*x+b`. Используя вложенные области видимости:505506```python507def linear(a, b):508    def result(x):509        return a * x + b510    return result511```512513Или используя вызываемый объект:514515```python516class linear:517518    def __init__(self, a, b):519        self.a, self.b = a, b520521    def __call__(self, x):522        return self.a * x + self.b523```524525В обоих случаях526527```python528taxes = linear(0.3, 2)529```530531даёт вызываемый объект, где `taxes(10e6) == 0.3 * 10e6 + 2`.532533Подход с вызываемым объектом имеет недостаток: он немного медленнее и\\nприводит к чуть более длинному коду. Однако обратите внимание, что набор вызываемых объектов\\nможет разделять свою сигнатуру через наследование:534535```python536class exponential(linear):537    # __init__ унаследован538    def __call__(self, x):539        return self.a * (x ** self.b)540```541542Объект может инкапсулировать состояние для нескольких методов:543544```python545class counter:546547    value = 0548549    def set(self, x):550        self.value = x551552    def up(self):553        self.value = self.value + 1554555    def down(self):556        self.value = self.value - 1557558count = counter()559inc, dec, reset = count.up, count.down, count.set560```561562Здесь `inc()`, `dec()` и `reset()` ведут себя как функции, которые разделяют одну\\nи ту же переменную счётчика.563564### [Как скопировать объект в Python?](https://python-all.ru/3.7/faq/programming.html#id19)565566В общем случае для копирования попробуйте [`copy.copy()`](https://python-all.ru/3.7/library/copy.html#copy.copy) или [`copy.deepcopy()`](https://python-all.ru/3.7/library/copy.html#copy.deepcopy).\\nНе все объекты можно копировать, но большинство можно.567568Некоторые объекты можно скопировать проще. У словарей есть метод [`copy()`](https://python-all.ru/3.7/library/stdtypes.html#dict.copy):569570```python571newdict = olddict.copy()572```573574Последовательности можно скопировать срезом:575576```python577new_l = l[:]578```579580### [Как найти методы или атрибуты объекта?](https://python-all.ru/3.7/faq/programming.html#id20)581582Для экземпляра x пользовательского класса `dir(x)` возвращает отсортированный по алфавиту список имён, содержащий атрибуты экземпляра, методы и атрибуты, определённые в его классе.583584### [Как код может узнать имя объекта?](https://python-all.ru/3.7/faq/programming.html#id21)585586Вообще говоря, никак, потому что у объектов на самом деле нет имён. По сути, присваивание всегда связывает имя со значением; то же верно для операторов `def` и `class`, но в этом случае значение является вызываемым объектом. Рассмотрим следующий код:587588```python589>>> class A:590...     pass591...592>>> B = A593>>> a = B()594>>> b = a595>>> print(b)596<__main__.A object at 0x16D07CC>597>>> print(a)598<__main__.A object at 0x16D07CC>599```600601Можно утверждать, что у класса есть имя: даже если он привязан к двум именам и вызывается через имя B, созданный экземпляр всё равно будет определён как экземпляр класса A. Однако невозможно сказать, какое имя у экземпляра – a или b, поскольку оба имени привязаны к одному и тому же значению.602603Вообще говоря, коду не требуется «знать имена» конкретных значений. Если вы не пишете намеренно интроспективные программы, это обычно указывает на то, что стоит изменить подход.604605В comp.lang.python Фредрик Лунд однажды привёл отличную аналогию в ответ на этот вопрос:606607> Так же, как вы узнаёте имя кота, которого нашли на крыльце: сам кот (объект) не может сказать вам своё имя, да ему всё равно – поэтому единственный способ выяснить, как его зовут, – спросить всех соседей (пространства имён), не их ли это кот (объект)…608>609> …и не удивляйтесь, если окажется, что он известен под многими именами или вообще без имени!610611### [Что не так с приоритетом оператора-запятой?](https://python-all.ru/3.7/faq/programming.html#id22)612613Запятая в Python – не оператор. Рассмотрим такой сеанс:614615```python616>>> "a" in "b", "a"617(False, 'a')618```619620Поскольку запятая – не оператор, а разделитель между выражениями, приведённый выше код выполняется так, как если бы вы ввели:621622```python623("a" in "b"), "a"624```625626а не:627628```python629"a" in ("b", "a")630```631632То же самое верно для различных операторов присваивания (`=`, `+=` и т. д.). Они не являются операторами в полном смысле, а представляют собой синтаксические разделители в операторах присваивания.633634### [Существует ли аналог тернарного оператора «?:» из C?](https://python-all.ru/3.7/faq/programming.html#id23)635636Да, существует. Синтаксис следующий:637638```python639[on_true] if [expression] else [on_false]640641x, y = 50, 25642small = x if x < y else y643```644645До введения этого синтаксиса в Python 2.5 распространённым приёмом было использование логических операторов:646647```python648[expression] and [on_true] or [on_false]649```650651Однако этот приём небезопасен, поскольку может давать неверные результаты, если *on\_true* имеет ложное булево значение. Поэтому всегда лучше использовать форму `... if ... else ...`.652653### [Можно ли писать запутанные однострочники на Python?](https://python-all.ru/3.7/faq/programming.html#id24)654655Да. Обычно это делается вложением [`lambda`](https://python-all.ru/3.7/reference/expressions.html#lambda) внутрь `lambda`. См. следующие три примера, предоставленные Ульфом Бартельтом:656657```python658from functools import reduce659660# Простые числа < 1000661print(list(filter(None,map(lambda y:y*reduce(lambda x,y:x*y!=0,662map(lambda x,y=y:y%x,range(2,int(pow(y,0.5)+1))),1),range(2,1000)))))663664# Первые 10 чисел Фибоначчи665print(list(map(lambda x,f=lambda x,f:(f(x-1,f)+f(x-2,f)) if x>1 else 1:666f(x,f), range(10))))667668# Множество Мандельброта669print((lambda Ru,Ro,Iu,Io,IM,Sx,Sy:reduce(lambda x,y:x+y,map(lambda y,670Iu=Iu,Io=Io,Ru=Ru,Ro=Ro,Sy=Sy,L=lambda yc,Iu=Iu,Io=Io,Ru=Ru,Ro=Ro,i=IM,671Sx=Sx,Sy=Sy:reduce(lambda x,y:x+y,map(lambda x,xc=Ru,yc=yc,Ru=Ru,Ro=Ro,672i=i,Sx=Sx,F=lambda xc,yc,x,y,k,f=lambda xc,yc,x,y,k,f:(k<=0)or (x*x+y*y673>=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(67464+F(Ru+x*(Ro-Ru)/Sx,yc,0,0,i)),range(Sx))):L(Iu+y*(Io-Iu)/Sy),range(Sy675))))(-2.1, 0.7, -1.2, 1.2, 30, 80, 24))676#    \___ ___/  \___ ___/  |   |   |__ линии на экране677#        V          V      |   |______ столбцы на экране678#        |          |      |__________ максимум "iterations"679#        |          |_________________ диапазон по оси Y680#        |____________________________ диапазон по оси X681```682683Не пытайтесь повторить это дома, дети!684685### [Что означает косая черта (/) в списке параметров функции?](https://python-all.ru/3.7/faq/programming.html#id25)686687Косая черта в списке аргументов функции обозначает, что параметры перед ней являются только позиционными. Позиционно-обязательные параметры – это те, которые не имеют внешне используемого имени. При вызове функции, принимающей только позиционные параметры, аргументы сопоставляются параметрам исключительно на основе их позиции. Например, [`pow()`](https://python-all.ru/3.7/library/functions.html#pow) – это функция, которая принимает только позиционные параметры. Её документация выглядит так:688689```python690>>> help(pow)691Help on built-in function pow in module builtins:692693pow(x, y, z=None, /)694   Equivalent to x**y (with two arguments) or x**y % z (with three arguments)695696   Some types, such as ints, are able to use a more efficient algorithm when697   invoked using the three argument form.698```699700Косая черта в конце списка параметров означает, что все три параметра являются только позиционными. Таким образом, вызов [`pow()`](https://python-all.ru/3.7/library/functions.html#pow) с именованными аргументами приведёт к ошибке:701702```python703>>> pow(x=3, y=4)704Traceback (most recent call last):705  File "<stdin>", line 1, in <module>706TypeError: pow() takes no keyword arguments707```708709Обратите внимание, что на момент написания это только документационное соглашение и не является допустимым синтаксисом в Python, хотя существует [**PEP 570**](https://python-all.ru/3.7/faq/programming.html), который предлагает синтаксис для только позиционных параметров в Python.710711## [Числа и строки](https://python-all.ru/3.7/faq/programming.html#id26)712713### [Как задать шестнадцатеричные и восьмеричные целые числа?](https://python-all.ru/3.7/faq/programming.html#id27)714715Чтобы задать восьмеричное число, поставьте перед восьмеричным значением ноль, а затем строчную или прописную букву «o». Например, чтобы присвоить переменной «a» восьмеричное значение «10» (8 в десятичной системе), введите:716717```python718>>> a = 0o10719>>> a7208721```722723Шестнадцатеричные числа задаются так же просто. Просто поставьте перед шестнадцатеричным числом ноль, а затем строчную или прописную «x». Шестнадцатеричные цифры можно указывать в нижнем или верхнем регистре. Например, в интерпретаторе Python:724725```python726>>> a = 0xa5727>>> a728165729>>> b = 0XB2730>>> b731178732```733734### [Почему -22 // 10 возвращает -3?](https://python-all.ru/3.7/faq/programming.html#id28)735736В первую очередь это вызвано желанием, чтобы `i % j` имел тот же знак, что и `j`. Если вы хотите этого, а также хотите:737738```python739i == (i // j) * j + (i % j)740```741742тогда целочисленное деление должно возвращать пол (округление вниз). Язык C также требует выполнения этого тождества, и тогда компиляторы, усекающие `i // j`, должны делать так, чтобы `i % j` имел тот же знак, что и `i`.743744Существует мало реальных применений `i % j`, когда `j` отрицательно. Когда `j` положительно, применений много, и практически во всех из них полезнее, чтобы `i % j` было `>= 0`. Если часы показывают 10 сейчас, что они показывали 200 часов назад? `-190 % 12 == 2` полезно; `-190 % 12 == -10` – это ошибка, которая только и ждёт, чтобы её допустили.745746### [Как преобразовать строку в число?](https://python-all.ru/3.7/faq/programming.html#id29)747748Для целых чисел используйте встроенный конструктор типа [`int()`](https://python-all.ru/3.7/library/functions.html#int), например `int('144') == 144`. Аналогично, [`float()`](https://python-all.ru/3.7/library/functions.html#float) преобразует в число с плавающей запятой, например `float('144') == 144.0`.749750По умолчанию они интерпретируют число как десятичное, так что `int('0144') == 144` и `int('0x144')` вызывает [`ValueError`](https://python-all.ru/3.7/library/exceptions.html#ValueError). `int(string, base)` принимает основание системы счисления в качестве второго необязательного аргумента, поэтому `int('0x144', 16) == 324`. Если основание задано как 0, число интерпретируется по правилам Python: префикс '0o' означает восьмеричную, а '0x' – шестнадцатеричную систему.751752Не используйте встроенную функцию [`eval()`](https://python-all.ru/3.7/library/functions.html#eval), если нужно просто преобразовать строку в число. [`eval()`](https://python-all.ru/3.7/library/functions.html#eval) будет работать значительно медленнее и создаёт угрозу безопасности: кто-то может передать Python-выражение с нежелательными побочными эффектами. Например, можно передать `__import__('os').system("rm -rf $HOME")`, что приведёт к удалению вашего домашнего каталога.753754[`eval()`](https://python-all.ru/3.7/library/functions.html#eval) также интерпретирует числа как выражения Python, поэтому, например, `eval('09')` вызывает синтаксическую ошибку, поскольку Python не допускает ведущий ‘0’ в десятичном числе (кроме ‘0’).755756### [Как преобразовать число в строку?](https://python-all.ru/3.7/faq/programming.html#id30)757758Чтобы преобразовать, например, число 144 в строку '144', используйте встроенный конструктор типа [`str()`](https://python-all.ru/3.7/library/stdtypes.html#str). Если нужно шестнадцатеричное или восьмеричное представление, используйте встроенные функции [`hex()`](https://python-all.ru/3.7/library/functions.html#hex) или [`oct()`](https://python-all.ru/3.7/library/functions.html#oct). Для расширенного форматирования см. разделы [Форматированные строковые литералы](https://python-all.ru/3.7/reference/lexical_analysis.html#f-strings) и [Синтаксис форматных строк](https://python-all.ru/3.7/library/string.html#formatstrings), например `"{:04d}".format(144)` даёт `'0144'`, а `"{:.3f}".format(1.0/3.0)` даёт `'0.333'`.759760### [Как изменить строку на месте?](https://python-all.ru/3.7/faq/programming.html#id31)761762Нельзя, потому что строки неизменяемы. В большинстве случаев следует просто создавать новую строку из тех частей, из которых вы хотите её собрать. Однако, если нужен объект с возможностью изменять данные Unicode на месте, попробуйте использовать объект [`io.StringIO`](https://python-all.ru/3.7/library/io.html#io.StringIO) или модуль [`array`](https://python-all.ru/3.7/library/array.html#module-array) :763764```python765>>> import io766>>> s = "Hello, world"767>>> sio = io.StringIO(s)768>>> sio.getvalue()769'Hello, world'770>>> sio.seek(7)7717772>>> sio.write("there!")7736774>>> sio.getvalue()775'Hello, there!'776777>>> import array778>>> a = array.array('u', s)779>>> print(a)780array('u', 'Hello, world')781>>> a[0] = 'y'782>>> print(a)783array('u', 'yello, world')784>>> a.tounicode()785'yello, world'786```787788### [Как использовать строки для вызова функций/методов?](https://python-all.ru/3.7/faq/programming.html#id32)789790Существует несколько приёмов.791792- Лучший из них – использовать словарь, сопоставляющий строки с функциями. Главное преимущество этого подхода в том, что строки не обязаны совпадать с именами функций. Это также основной способ эмуляции конструкции case:793794  ```python795  def a():796      pass797798  def b():799      pass800801  dispatch = {'go': a, 'stop': b}  # Обратите внимание на отсутствие скобок для функций802803  dispatch[get_input()]()  # Обратите внимание на завершающие скобки для вызова функции804  ```805- Используйте встроенную функцию [`getattr()`](https://python-all.ru/3.7/library/functions.html#getattr):806807  ```python808  import foo809  getattr(foo, 'bar')()810  ```811812  Обратите внимание: [`getattr()`](https://python-all.ru/3.7/library/functions.html#getattr) работает с любыми объектами, включая классы, экземпляры классов, модули и т.д.813814  Это используется в нескольких местах стандартной библиотеки, например:815816  ```python817  class Foo:818      def do_foo(self):819          ...820821      def do_bar(self):822          ...823824  f = getattr(foo_instance, 'do_' + opname)825  f()826  ```827- Используйте [`locals()`](https://python-all.ru/3.7/library/functions.html#locals) или [`eval()`](https://python-all.ru/3.7/library/functions.html#eval) для разрешения имени функции:828829  ```python830  def myFunc():831      print("hello")832833  fname = "myFunc"834835  f = locals()[fname]836  f()837838  f = eval(fname)839  f()840  ```841842  Примечание: использование [`eval()`](https://python-all.ru/3.7/library/functions.html#eval) медленно и опасно. Если у вас нет абсолютного контроля над содержимым строки, кто-то может передать строку, которая приведёт к выполнению произвольной функции.843844### [Существует ли аналог функции chomp() из Perl для удаления завершающих символов новой строки из строк?](https://python-all.ru/3.7/faq/programming.html#id33)845846Можно использовать `S.rstrip("\r\n")` для удаления всех символов конца строки в конце строки `S`, не затрагивая остальные пробельные символы. Если строка `S` содержит несколько строк с пустыми строками в конце, будут удалены завершающие символы для всех пустых строк:847848```python849>>> lines = ("line 1 \r\n"850...          "\r\n"851...          "\r\n")852>>> lines.rstrip("\n\r")853'line 1 '854```855856Поскольку такой подход обычно нужен только при чтении текста построчно, `S.rstrip()` в таком виде отлично подходит.857858### [Существует ли аналог функций scanf() или sscanf()?](https://python-all.ru/3.7/faq/programming.html#id34)859860Прямого аналога нет.861862Для простого разбора ввода проще всего разбить строку на слова, разделённые пробельными символами, с помощью метода [`split()`](https://python-all.ru/3.7/library/stdtypes.html#str.split) строковых объектов, а затем преобразовать десятичные строки в числа через [`int()`](https://python-all.ru/3.7/library/functions.html#int) или [`float()`](https://python-all.ru/3.7/library/functions.html#float). Функция `split()` поддерживает необязательный параметр «sep», который удобен, если разделителем выступает не пробел.863864Для более сложного разбора ввода регулярные выражения мощнее, чем C-функция `sscanf()`, и лучше подходят для этой задачи.865866### [Что означает ошибка UnicodeDecodeError или UnicodeEncodeError?](https://python-all.ru/3.7/faq/programming.html#id35)867868Смотрите [Unicode HOWTO](https://python-all.ru/3.7/howto/unicode.html#unicode-howto).869870## [Производительность](https://python-all.ru/3.7/faq/programming.html#id36)871872### [Моя программа слишком медленная. Как её ускорить?](https://python-all.ru/3.7/faq/programming.html#id37)873874В целом это непростой вопрос. Во-первых, вот список того, что стоит помнить, прежде чем углубляться:875876- Характеристики производительности различаются в разных реализациях Python. Этот FAQ сосредоточен на [CPython](https://python-all.ru/3.7/glossary.html#term-cpython).877- Поведение может различаться в разных операционных системах, особенно когда речь идёт о вводе-выводе или многопоточности.878- всегда следует находить горячие точки в своей программе *перед* попыткой оптимизировать какой-либо код (см. модуль [`profile`](https://python-all.ru/3.7/library/profile.html#module-profile)).879- Написание эталонных скриптов позволит быстро выполнять итерации при поиске улучшений (см. модуль [`timeit`](https://python-all.ru/3.7/library/timeit.html#module-timeit)).880- Настоятельно рекомендуется иметь хорошее покрытие кода (с помощью модульного тестирования или любой другой методики) перед возможным внесением регрессий, скрытых в сложных оптимизациях.881882Тем не менее, есть много приёмов для ускорения кода на Python. Вот некоторые общие принципы, которые сильно помогают достичь приемлемого уровня производительности:883884- Ускорение алгоритмов (или замена на более быстрые) может принести гораздо большую выгоду, чем попытки рассыпать микрооптимизации по всему коду.885- Используйте правильные структуры данных. Изучите документацию по [Встроенным типам](https://python-all.ru/3.7/library/stdtypes.html#bltin-types) и модулю [`collections`](https://python-all.ru/3.7/library/collections.html#module-collections).886- Когда стандартная библиотека предоставляет примитив для выполнения какой-либо операции, он, скорее всего (хотя и не гарантированно), будет быстрее любого альтернативного решения, которое вы можете придумать. Это вдвойне верно для примитивов, написанных на C, таких как встроенные функции и некоторые типы расширений. Например, обязательно используйте либо встроенный метод [`list.sort()`](https://python-all.ru/3.7/library/stdtypes.html#list.sort), либо соответствующую функцию [`sorted()`](https://python-all.ru/3.7/library/functions.html#sorted) для сортировки (и обратитесь к [Руководству по сортировке](https://python-all.ru/3.7/howto/sorting.html#sortinghowto) для примеров умеренно продвинутого использования).887- Абстракции обычно создают косвенность и заставляют интерпретатор работать больше. Если уровни косвенности перевешивают объём полезной работы, программа будет медленнее. Следует избегать чрезмерной абстракции, особенно в виде крошечных функций или методов (которые также часто вредят читаемости).888889Если вы достигли предела возможностей чистого Python, существуют инструменты, которые помогут пойти дальше. Например, [Cython](https://python-all.ru/3.7/faq/programming.html) может скомпилировать слегка изменённую версию кода Python в расширение C и может использоваться на многих разных платформах. Cython может использовать компиляцию (и необязательные аннотации типов), чтобы сделать ваш код значительно быстрее, чем при интерпретации. Если вы уверены в своих навыках программирования на C, вы также можете самостоятельно [написать модуль расширения на C](https://python-all.ru/3.7/extending/index.html#extending-index).890891> **См. также**892>893> Вики-страница, посвящённая [советам по производительности](https://python-all.ru/3.7/faq/programming.html).894895### [Как наиболее эффективно объединить много строк?](https://python-all.ru/3.7/faq/programming.html#id38)896897Объекты [`str`](https://python-all.ru/3.7/library/stdtypes.html#str) и [`bytes`](https://python-all.ru/3.7/library/stdtypes.html#bytes) неизменяемы, поэтому объединение множества строк неэффективно, поскольку каждое объединение создаёт новый объект. В общем случае общая стоимость выполнения квадратично зависит от общей длины строк.898899Для накопления множества объектов [`str`](https://python-all.ru/3.7/library/stdtypes.html#str) рекомендуется помещать их в список и в конце вызвать [`str.join()`](https://python-all.ru/3.7/library/stdtypes.html#str.join):900901```python902chunks = []903for s in my_strings:904    chunks.append(s)905result = ''.join(chunks)906```907908(ещё один достаточно эффективный приём – использовать [`io.StringIO`](https://python-all.ru/3.7/library/io.html#io.StringIO))909910Для накопления множества объектов [`bytes`](https://python-all.ru/3.7/library/stdtypes.html#bytes) рекомендуется расширять объект [`bytearray`](https://python-all.ru/3.7/library/stdtypes.html#bytearray) с помощью конкатенации на месте (оператор `+=`):911912```python913result = bytearray()914for b in my_bytes_objects:915    result += b916```917918## [Последовательности (кортежи/списки)](https://python-all.ru/3.7/faq/programming.html#id39)919920### [Как преобразовывать кортежи и списки друг в друга?](https://python-all.ru/3.7/faq/programming.html#id40)921922Конструктор типа `tuple(seq)` преобразует любую последовательность (на самом деле любой итерируемый объект) в кортеж с теми же элементами в том же порядке.923924Например, `tuple([1, 2, 3])` даёт `(1, 2, 3)`, а `tuple('abc')` даёт `('a', 'b', 'c')`. Если аргумент уже является кортежем, копия не создаётся – возвращается тот же объект, поэтому вызов [`tuple()`](https://python-all.ru/3.7/library/stdtypes.html#tuple) обходится дёшево, когда нет уверенности, что объект уже является кортежем.925926Конструктор типа `list(seq)` преобразует любую последовательность или итерируемый объект в список с теми же элементами в том же порядке. Например, `list((1, 2, 3))` даёт `[1, 2, 3]`, а `list('abc')` даёт `['a', 'b', 'c']`. Если аргумент является списком, создаётся копия, как и в случае `seq[:]`.927928### [Что такое отрицательный индекс?](https://python-all.ru/3.7/faq/programming.html#id41)929930Последовательности Python индексируются положительными и отрицательными числами. Для положительных чисел 0 – это первый индекс, 1 – второй и так далее. Для отрицательных индексов -1 – последний индекс, -2 – предпоследний (перед последним) и так далее. Считайте `seq[-n]` тем же, что и `seq[len(seq)-n]`.931932Использование отрицательных индексов может быть очень удобным. Например, `S[:-1]` – это вся строка, кроме последнего символа, что полезно для удаления завершающего перевода строки.933934### [Как перебрать последовательность в обратном порядке?](https://python-all.ru/3.7/faq/programming.html#id42)935936Используйте встроенную функцию [`reversed()`](https://python-all.ru/3.7/library/functions.html#reversed), которая появилась в Python 2.4:937938```python939for x in reversed(sequence):940    ...  # сделать что-то с x ...941```942943Это не затронет исходную последовательность, а создаст новую копию с обратным порядком для итерации.944945В Python 2.3 можно использовать расширенный синтаксис срезов:946947```python948for x in sequence[::-1]:949    ...  # сделать что-то с x ...950```951952### [Как удалить дубликаты из списка?](https://python-all.ru/3.7/faq/programming.html#id43)953954См. Python Cookbook, где подробно рассматриваются многие способы сделать это:955956> [https://code.activestate.com/recipes/52560/](https://python-all.ru/3.7/faq/programming.html)957958Если перестановка элементов списка не страшна, отсортируйте его, а затем просмотрите с конца, удаляя дубликаты по ходу:959960```python961if mylist:962    mylist.sort()963    last = mylist[-1]964    for i in range(len(mylist)-2, -1, -1):965        if last == mylist[i]:966            del mylist[i]967        else:968            last = mylist[i]969```970971Если все элементы списка могут использоваться как ключи множества (т.е. все они [хешируемы](https://python-all.ru/3.7/glossary.html#term-hashable)), это часто быстрее972973```python974mylist = list(set(mylist))975```976977Это преобразует список во множество, удаляя дубликаты, а затем обратно в список.978979### [Как создать массив в Python?](https://python-all.ru/3.7/faq/programming.html#id44)980981Используйте список:982983```python984["this", 1, "is", "an", "array"]985```986987По временно́й сложности списки эквивалентны массивам C или Pascal; основное отличие в том, что список Python может содержать объекты разных типов.988989Модуль `array` также предоставляет методы для создания массивов фиксированных типов с компактным представлением, но они медленнее при индексации, чем списки. Также обратите внимание, что расширения Numeric и другие определяют структуры, подобные массивам, с различными характеристиками.990991Чтобы получить связные списки в стиле Lisp, можно эмулировать ячейки cons с помощью кортежей:992993```python994lisp_list = ("like",  ("this",  ("example", None) ) )995```996997Если нужна изменяемость, можно использовать списки вместо кортежей. Здесь аналог lisp car – это `lisp_list[0]`, а аналог cdr – `lisp_list[1]`. Делайте так, только если уверены, что это действительно необходимо, потому что обычно это намного медленнее, чем использование списков Python.998999### [Как создать многомерный список?](https://python-all.ru/3.7/faq/programming.html#id45)10001001Вероятно, вы пытались создать многомерный массив так:10021003```python1004>>> A = [[None] * 2] * 31005```10061007Если вывести его, выглядит правильно:10081009```pycon1010>>> A1011[[None, None], [None, None], [None, None]]1012```10131014Но когда вы присваиваете значение, оно появляется в нескольких местах:10151016```pycon1017>>> A[0][0] = 51018>>> A1019[[5, None], [5, None], [5, None]]1020```10211022Причина в том, что размножение списка с помощью `*` не создаёт копии, а только ссылки на существующие объекты. `*3` создаёт список из 3 ссылок на один и тот же список длины два. Изменения в одной строке отразятся во всех строках, что почти наверняка не то, что нужно.10231024Рекомендуемый подход – сначала создать список нужной длины, а затем заполнить каждый элемент заново созданным списком:10251026```python1027A = [None] * 31028for i in range(3):1029    A[i] = [None] * 21030```10311032Это порождает список, содержащий 3 разных списка длины два. Также можно использовать списковое включение:10331034```python1035w, h = 2, 31036A = [[None] * w for i in range(h)]1037```10381039Или можно воспользоваться расширением, предоставляющим тип данных «матрица»; наиболее известен [NumPy](https://python-all.ru/3.7/faq/programming.html).10401041### [Как применить метод к последовательности объектов?](https://python-all.ru/3.7/faq/programming.html#id46)10421043Используйте списковое включение:10441045```python1046result = [obj.method() for obj in mylist]1047```10481049### [Почему a\_tuple\[i\] += \['item'\] вызывает исключение, хотя сложение работает?](https://python-all.ru/3.7/faq/programming.html#id47)10501051Это связано с тем, что операторы расширенного присваивания являются *операторами присваивания*, а также с различием между изменяемыми и неизменяемыми объектами в Python.10521053Это обсуждение в целом применимо, когда операторы расширенного присваивания применяются к элементам кортежа, указывающим на изменяемые объекты, но в качестве примера мы используем `list` и `+=`.10541055Если написать:10561057```python1058>>> a_tuple = (1, 2)1059>>> a_tuple[0] += 11060Traceback (most recent call last):1061   ...1062TypeError: 'tuple' object does not support item assignment1063```10641065Причина исключения сразу становится ясна: `1` добавляется к объекту, на который указывает `a_tuple[0]` (`1`), в результате получается объект `2`, но когда мы пытаемся присвоить результат вычисления `2` элементу `0` кортежа, возникает ошибка, потому что нельзя изменить, на что указывает элемент кортежа.10661067На самом деле то, что делает этот расширенный оператор присваивания, примерно таково:10681069```python1070>>> result = a_tuple[0] + 11071>>> a_tuple[0] = result1072Traceback (most recent call last):1073  ...1074TypeError: 'tuple' object does not support item assignment1075```10761077Ошибку вызывает именно часть присваивания операции, поскольку кортеж неизменяем.10781079Если написать что-то вроде:10801081```python1082>>> a_tuple = (['foo'], 'bar')1083>>> a_tuple[0] += ['item']1084Traceback (most recent call last):1085  ...1086TypeError: 'tuple' object does not support item assignment1087```10881089Исключение несколько более неожиданно, и еще более удивительно то, что, несмотря на ошибку, append сработал:10901091```python1092>>> a_tuple[0]1093['foo', 'item']1094```10951096Чтобы понять, почему это происходит, нужно знать: (а) если объект реализует магический метод `__iadd__`, он вызывается, когда выполняется расширенное присваивание `+=`, и его возвращаемое значение используется в операторе присваивания; и (б) для списков `__iadd__` эквивалентно вызову `extend` для списка и возврату этого списка. Поэтому мы говорим, что для списков `+=` – это «сокращение» для `list.extend`:10971098```python1099>>> a_list = []1100>>> a_list += [1]1101>>> a_list1102[1]1103```11041105Это эквивалентно:11061107```python1108>>> result = a_list.__iadd__([1])1109>>> a_list = result1110```11111112Объект, на который указывает a\_list, был изменён, и указатель на изменённый объект присваивается обратно `a_list`. Конечный результат присваивания – холостая операция (no-op), поскольку это указатель на тот же объект, на который `a_list` указывал ранее, но само присваивание всё равно происходит.11131114Таким образом, в нашем примере с кортежем происходит то же самое, что и в:11151116```python1117>>> result = a_tuple[0].__iadd__(['item'])1118>>> a_tuple[0] = result1119Traceback (most recent call last):1120  ...1121TypeError: 'tuple' object does not support item assignment1122```11231124`__iadd__` выполняется успешно, и список расширяется, но, хотя `result` указывает на тот же объект, на который уже указывает `a_tuple[0]`, финальное присваивание всё равно вызывает ошибку, поскольку кортежи неизменяемы.11251126### [Я хочу выполнить сложную сортировку: можно ли сделать преобразование Шварца в Python?](https://python-all.ru/3.7/faq/programming.html#id48)11271128Этот метод, приписываемый Рэндалу Шварцу из сообщества Perl, сортирует элементы списка по метрике, которая сопоставляет каждому элементу его «сортировочное значение». В Python используйте аргумент `key` для метода [`list.sort()`](https://python-all.ru/3.7/library/stdtypes.html#list.sort):11291130```python1131Isorted = L[:]1132Isorted.sort(key=lambda s: int(s[10:15]))1133```11341135### [Как отсортировать один список по значениям из другого списка?](https://python-all.ru/3.7/faq/programming.html#id49)11361137Объедините их в итератор кортежей, отсортируйте полученный список, а затем извлеките нужный элемент.11381139```python1140>>> list1 = ["what", "I'm", "sorting", "by"]1141>>> list2 = ["something", "else", "to", "sort"]1142>>> pairs = zip(list1, list2)1143>>> pairs = sorted(pairs)1144>>> pairs1145[("I'm", 'else'), ('by', 'sort'), ('sorting', 'to'), ('what', 'something')]1146>>> result = [x[1] for x in pairs]1147>>> result1148['else', 'sort', 'to', 'something']1149```11501151Альтернатива для последнего шага:11521153```python1154>>> result = []1155>>> for p in pairs: result.append(p[1])1156```11571158Если вам это кажется более читаемым, вы можете предпочесть использовать это вместо конечного спискового включения. Однако для длинных списков это почти в два раза медленнее. Почему? Во-первых, операция `append()` должна перераспределять память, и хотя она использует некоторые трюки, чтобы избегать этого каждый раз, иногда ей всё же приходится это делать, что стоит довольно дорого. Во-вторых, выражение «result.append» требует дополнительного поиска атрибута, и в-третьих, скорость снижается из-за необходимости совершать все эти вызовы функций.11591160## [Объекты](https://python-all.ru/3.7/faq/programming.html#id50)11611162### [Что такое класс?](https://python-all.ru/3.7/faq/programming.html#id51)11631164Класс – это конкретный тип объекта, создаваемый при выполнении инструкции class. Объекты классов используются как шаблоны для создания объектов-экземпляров, которые содержат как данные (атрибуты), так и код (методы), характерные для данного типа данных.11651166Класс может быть основан на одном или нескольких других классах, называемых его базовыми классами. Он наследует атрибуты и методы своих базовых классов. Это позволяет последовательно уточнять объектную модель с помощью наследования. Например, можно иметь общий класс `Mailbox`, предоставляющий базовые методы доступа к почтовому ящику, и подклассы `MboxMailbox`, `MaildirMailbox`, `OutlookMailbox`, обрабатывающие различные форматы почтовых ящиков.11671168### [Что такое метод?](https://python-all.ru/3.7/faq/programming.html#id52)11691170Метод – это функция некоторого объекта `x`, которая обычно вызывается как `x.name(arguments...)`. Методы определяются как функции внутри определения класса:11711172```python1173class C:1174    def meth(self, arg):1175        return arg * 2 + self.attribute1176```11771178### [Что такое self?](https://python-all.ru/3.7/faq/programming.html#id53)11791180Self – это просто условное имя для первого аргумента метода. Метод, определённый как `meth(self, a, b, c)`, должен вызываться как `x.meth(a, b, c)` для некоторого экземпляра `x` класса, в котором находится определение; вызванный метод будет считать, что его вызвали как `meth(x, a, b, c)`.11811182См. также [Почему self должно явно использоваться в определениях и вызовах методов?](https://python-all.ru/3.7/faq/design.html#why-self).11831184### [Как проверить, является ли объект экземпляром данного класса или его подкласса?](https://python-all.ru/3.7/faq/programming.html#id54)11851186Используйте встроенную функцию `isinstance(obj, cls)`. Можно проверить, является ли объект экземпляром любого из нескольких классов, передав кортеж вместо одного класса, например `isinstance(obj, (class1, class2, ...))`, а также проверить, является ли объект одним из встроенных типов Python, например `isinstance(obj, str)` или `isinstance(obj, (int, float, complex))`.11871188Обратите внимание, что большинство программ не используют [`isinstance()`](https://python-all.ru/3.7/library/functions.html#isinstance) для пользовательских классов очень часто. Если вы разрабатываете классы сами, более правильным объектно-ориентированным стилем будет определение методов в классах, инкапсулирующих определённое поведение, вместо проверки класса объекта и выполнения разных действий в зависимости от того, какой это класс. Например, если есть функция, которая делает что-то:11891190```python1191def search(obj):1192    if isinstance(obj, Mailbox):1193        ...  # код для поиска почтового ящика1194    elif isinstance(obj, Document):1195        ...  # код для поиска документа1196    elif ...1197```11981199Лучше определить метод `search()` во всех классах и просто вызывать его:12001201```python1202class Mailbox:1203    def search(self):1204        ...  # код для поиска почтового ящика12051206class Document:1207    def search(self):1208        ...  # код для поиска документа12091210obj.search()1211```12121213### [Что такое делегирование?](https://python-all.ru/3.7/faq/programming.html#id55)12141215Делегирование – это объектно-ориентированная техника (также называемая шаблоном проектирования). Допустим, у вас есть объект `x` и нужно изменить поведение только одного из его методов. Можно создать новый класс, который предоставляет новую реализацию интересующего метода и делегирует все остальные методы соответствующему методу объекта `x`.12161217Программисты на Python могут легко реализовать делегирование. Например, следующий класс реализует класс, который ведёт себя как файл, но преобразует все записываемые данные в верхний регистр:12181219```python1220class UpperOut:12211222    def __init__(self, outfile):1223        self._outfile = outfile12241225    def write(self, s):1226        self._outfile.write(s.upper())12271228    def __getattr__(self, name):1229        return getattr(self._outfile, name)1230```12311232Here 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/3.7/reference/datamodel.html#attribute-access) for more information about controlling attribute access.12331234Обратите внимание, что в более общих случаях делегирование может усложниться. Если атрибуты нужно не только получать, но и устанавливать, класс должен также определить метод [`__setattr__()`](https://python-all.ru/3.7/reference/datamodel.html#object.__setattr__), и делать это нужно аккуратно. Базовая реализация [`__setattr__()`](https://python-all.ru/3.7/reference/datamodel.html#object.__setattr__) примерно эквивалентна следующему:12351236```python1237class X:1238    ...1239    def __setattr__(self, name, value):1240        self.__dict__[name] = value1241    ...1242```12431244Большинство реализаций [`__setattr__()`](https://python-all.ru/3.7/reference/datamodel.html#object.__setattr__) должны изменять `self.__dict__` для хранения локального состояния для self, чтобы избежать бесконечной рекурсии.12451246### [Как вызвать метод, определённый в базовом классе, из производного класса, который его переопределяет?](https://python-all.ru/3.7/faq/programming.html#id56)12471248Используйте встроенную функцию [`super()`](https://python-all.ru/3.7/library/functions.html#super):12491250```python1251class Derived(Base):1252    def meth(self):1253        super(Derived, self).meth()1254```12551256Для версий до 3.0 могут использоваться классические классы: для определения класса, например `class Derived(Base): ...`, можно вызвать метод `meth()`, определённый в `Base` (или в одном из базовых классов `Base`), как `Base.meth(self, arguments...)`. Здесь `Base.meth` – это непривязанный метод, поэтому нужно передать аргумент `self`.12571258### [Как организовать код, чтобы было проще изменить базовый класс?](https://python-all.ru/3.7/faq/programming.html#id57)12591260Можно определить псевдоним для базового класса, присвоить ему реальный базовый класс до определения вашего класса и использовать псевдоним во всём классе. Тогда всё, что нужно изменить – это значение, присвоенное псевдониму. Кстати, этот трюк также удобен, если вы хотите динамически (например, в зависимости от доступности ресурсов) выбирать, какой базовый класс использовать. Пример:12611262```python1263BaseAlias = <real base class>12641265class Derived(BaseAlias):1266    def meth(self):1267        BaseAlias.meth(self)1268        ...1269```12701271### [Как создать статические данные класса и статические методы класса?](https://python-all.ru/3.7/faq/programming.html#id58)12721273В Python поддерживаются как статические данные, так и статические методы (в смысле C++ или Java).12741275Для статических данных просто определите атрибут класса. Чтобы присвоить атрибуту новое значение, необходимо явно указать имя класса в присваивании:12761277```python1278class C:1279    count = 0   # количество вызовов C.__init__12801281    def __init__(self):1282        C.count = C.count + 112831284    def getcount(self):1285        return C.count  # или вернуть self.count1286```12871288`c.count` также ссылается на `C.count` для любого `c`, для которого `isinstance(c, C)` истинно, если только оно не переопределено самим `c` или каким-либо классом на пути поиска базового класса от `c.__class__` до `C`.12891290Внимание: внутри метода C присваивание вида `self.count = 42` создаёт новый и не связанный экземпляр с именем «count» в собственном словаре `self`. Повторное связывание имени статических данных класса всегда должно указывать класс, как внутри метода, так и вне его:12911292```python1293C.count = 3141294```12951296Статические методы возможны:12971298```python1299class C:1300    @staticmethod1301    def static(arg1, arg2, arg3):1302        # Нет параметра 'self'!1303        ...1304```13051306Однако гораздо более прямолинейный способ получить эффект статического метода – это простая функция уровня модуля:13071308```python1309def getcount():1310    return C.count1311```13121313Если код организован так, что на каждый модуль определён один класс (или тесно связанная иерархия классов), это обеспечивает нужную инкапсуляцию.13141315### [Как перегрузить конструкторы (или методы) в Python?](https://python-all.ru/3.7/faq/programming.html#id59)13161317Этот ответ на самом деле применим ко всем методам, но вопрос обычно возникает в первую очередь в контексте конструкторов.13181319В C++ вы бы написали13201321```c1322class C {1323    C() { cout << "No arguments\n"; }1324    C(int i) { cout << "Argument is " << i << "\n"; }1325}1326```13271328В Python нужно написать один конструктор, который обрабатывает все случаи с помощью аргументов по умолчанию. Например:13291330```python1331class C:1332    def __init__(self, i=None):1333        if i is None:1334            print("No arguments")1335        else:1336            print("Argument is", i)1337```13381339Это не полностью эквивалентно, но на практике достаточно близко.13401341Можно также попробовать список аргументов переменной длины, например13421343```python1344def __init__(self, *args):1345    ...1346```13471348Тот же подход работает для всех определений методов.13491350### [Я пытаюсь использовать \_\_spam и получаю ошибку про \_SomeClassName\_\_spam.](https://python-all.ru/3.7/faq/programming.html#id60)13511352Имена переменных с двойным подчёркиванием в начале «искажаются» – это простой, но эффективный способ определения приватных переменных класса. Любой идентификатор вида `__spam` (не менее двух начальных подчёркиваний и не более одного конечного) текстуально заменяется на `_classname__spam`, где `classname` – это имя текущего класса без начальных подчёркиваний.13531354Это не гарантирует приватности: внешний пользователь все еще может намеренно получить доступ к атрибуту «\_classname\_\_spam», а приватные значения видны в `__dict__` объекта. Многие программисты на Python вообще не утруждают себя использованием имен приватных переменных.13551356### [Мой класс определяет \_\_del\_\_, но он не вызывается, когда я удаляю объект.](https://python-all.ru/3.7/faq/programming.html#id61)13571358Для этого есть несколько возможных причин.13591360Оператор del не обязательно вызывает [`__del__()`](https://python-all.ru/3.7/reference/datamodel.html#object.__del__) – он просто уменьшает счётчик ссылок объекта, и если он достигает нуля, вызывается [`__del__()`](https://python-all.ru/3.7/reference/datamodel.html#object.__del__).13611362Если ваши структуры данных содержат циклические ссылки (например, дерево, где каждый потомок имеет ссылку на родителя, а каждый родитель – список потомков), счётчики ссылок никогда не обнулятся. Время от времени Python запускает алгоритм для обнаружения таких циклов, но сборщик мусора может запуститься спустя некоторое время после того, как последняя ссылка на вашу структуру данных исчезнет, так что метод [`__del__()`](https://python-all.ru/3.7/reference/datamodel.html#object.__del__) может быть вызван в неудобный и случайный момент. Это неудобно, если вы пытаетесь воспроизвести проблему. Хуже того, порядок вызова методов [`__del__()`](https://python-all.ru/3.7/reference/datamodel.html#object.__del__) объектов произволен. Можно запустить [`gc.collect()`](https://python-all.ru/3.7/library/gc.html#gc.collect) для принудительной сборки, но существуют *патологические* случаи, когда объекты никогда не будут собраны.13631364Несмотря на сборщик циклов, всё равно рекомендуется определить явный метод `close()` для объектов, который будет вызываться, когда они больше не нужны. Метод `close()` может затем удалить атрибуты, ссылающиеся на подобъекты. Не вызывайте [`__del__()`](https://python-all.ru/3.7/reference/datamodel.html#object.__del__) напрямую – [`__del__()`](https://python-all.ru/3.7/reference/datamodel.html#object.__del__) должен вызывать `close()`, а `close()` должен гарантировать, что его можно вызвать более одного раза для одного и того же объекта.13651366Другой способ избежать циклических ссылок – использовать модуль [`weakref`](https://python-all.ru/3.7/library/weakref.html#module-weakref), который позволяет указывать на объекты без увеличения их счётчика ссылок. Например, структуры данных деревьев должны использовать слабые ссылки для ссылок на родительские и дочерние элементы (если они нужны!).13671368Наконец, если метод [`__del__()`](https://python-all.ru/3.7/reference/datamodel.html#object.__del__) вызывает исключение, предупреждение выводится в [`sys.stderr`](https://python-all.ru/3.7/library/sys.html#sys.stderr).13691370### [Как получить список всех экземпляров данного класса?](https://python-all.ru/3.7/faq/programming.html#id62)13711372Python не отслеживает все экземпляры класса (или встроенного типа). Можно запрограммировать конструктор класса так, чтобы он отслеживал все экземпляры, сохраняя список слабых ссылок на каждый экземпляр.13731374### [Почему результат `id()` кажется неуникальным?](https://python-all.ru/3.7/faq/programming.html#id63)13751376Встроенная функция [`id()`](https://python-all.ru/3.7/library/functions.html#id) возвращает целое число, которое гарантированно уникально в течение времени жизни объекта. Поскольку в CPython это адрес памяти объекта, часто бывает, что после удаления объекта из памяти следующий свежесозданный объект выделяется по тому же адресу. Это показано на следующем примере:13771378```python1379>>> id(1000) 1380139012721381>>> id(2000) 1382139012721383```13841385Два идентификатора принадлежат разным целочисленным объектам, которые создаются до и сразу же удаляются после выполнения вызова `id()`. Чтобы убедиться, что объекты, чей id нужно проверить, всё ещё живы, создайте ещё одну ссылку на объект:13861387```python1388>>> a = 1000; b = 20001389>>> id(a) 1390139012721391>>> id(b) 1392138912961393```13941395## [Модули](https://python-all.ru/3.7/faq/programming.html#id64)13961397### [Как создать .pyc-файл?](https://python-all.ru/3.7/faq/programming.html#id65)13981399Когда модуль импортируется впервые (или когда исходный файл изменился после создания текущего скомпилированного файла), в подкаталоге `__pycache__` каталога, содержащего файл `.py`, должен быть создан файл `.pyc` со скомпилированным кодом. Файл `.pyc` будет иметь имя, начинающееся с того же имени, что и файл `.py`, и заканчивающееся на `.pyc`, со средней частью, зависящей от конкретной двоичной сборки `python`, которая его создала. (Подробнее см. [**PEP 3147**](https://python-all.ru/3.7/faq/programming.html).)14001401Одна из причин, по которой файл `.pyc` может не создаваться, – проблема с правами доступа к каталогу, содержащему исходный файл: подкаталог `__pycache__` не может быть создан. Это может произойти, например, если вы разрабатываете от одного пользователя, а запускаете от другого, например, при тестировании с помощью веб-сервера.14021403Если не установлена переменная окружения [`PYTHONDONTWRITEBYTECODE`](https://python-all.ru/3.7/using/cmdline.html#envvar-PYTHONDONTWRITEBYTECODE), создание файла .pyc происходит автоматически при импорте модуля, если Python имеет возможность (права, свободное место и т.д.) создать подкаталог `__pycache__` и записать в него скомпилированный модуль.14041405Запуск Python на скрипте верхнего уровня не считается импортом, и `.pyc` не будет создан. Например, если есть модуль верхнего уровня `foo.py`, который импортирует другой модуль `xyz.py`, при запуске `foo` (путём ввода `python foo.py` как команды оболочки) будет создан `.pyc` для `xyz`, потому что `xyz` импортируется, но файл `.pyc` не будет создан для `foo`, поскольку `foo.py` не импортируется.14061407Если нужно создать файл `.pyc` для `foo`, то есть создать файл `.pyc` для модуля, который не импортируется, это можно сделать с помощью модулей [`py_compile`](https://python-all.ru/3.7/library/py_compile.html#module-py_compile) и [`compileall`](https://python-all.ru/3.7/library/compileall.html#module-compileall).14081409Модуль [`py_compile`](https://python-all.ru/3.7/library/py_compile.html#module-py_compile) может вручную скомпилировать любой модуль. Один из способов – интерактивно использовать функцию `compile()` в этом модуле:14101411```python1412>>> import py_compile1413>>> py_compile.compile('foo.py')                 1414```14151416Это запишет `.pyc` в подкаталог `__pycache__` в том же месте, что и `foo.py` (или это можно переопределить необязательным параметром `cfile`).14171418Также можно автоматически скомпилировать все файлы в каталоге или каталогах с помощью модуля [`compileall`](https://python-all.ru/3.7/library/compileall.html#module-compileall). Для этого из командной оболочки выполните `compileall.py` и укажите путь к каталогу, содержащему файлы Python для компиляции:14191420```python1421python -m compileall .1422```14231424### [Как узнать имя текущего модуля?](https://python-all.ru/3.7/faq/programming.html#id66)14251426Модуль может узнать своё собственное имя, обратившись к предопределённой глобальной переменной `__name__`. Если она равна `'__main__'`, программа выполняется как скрипт. Многие модули, которые обычно используются через импорт, также предоставляют интерфейс командной строки или самопроверку и выполняют этот код только после проверки `__name__`:14271428```python1429def main():1430    print('Running test...')1431    ...14321433if __name__ == '__main__':1434    main()1435```14361437### [Как сделать модули, которые импортируют друг друга?](https://python-all.ru/3.7/faq/programming.html#id67)14381439Предположим, у вас есть следующие модули:14401441foo.py:14421443```python1444from bar import bar_var1445foo_var = 11446```14471448bar.py:14491450```python1451from foo import foo_var1452bar_var = 21453```14541455Проблема в том, что интерпретатор выполнит следующие шаги:14561457- main импортирует foo1458- Создаются пустые глобальные переменные для foo1459- foo компилируется и начинает выполняться1460- foo импортирует bar1461- Создаются пустые глобальные переменные для bar1462- bar компилируется и начинает выполняться1463- bar импортирует foo (это пустая операция, так как модуль с именем foo уже существует)1464- bar.foo\_var = foo.foo\_var14651466Последний шаг завершается неудачей, потому что Python ещё не закончил интерпретацию `foo`, и словарь глобальных символов для `foo` всё ещё пуст.14671468То же самое происходит при использовании `import foo` и последующей попытке обратиться к `foo.foo_var` в глобальном коде.14691470Существует (как минимум) три возможных обходных решения этой проблемы.14711472Гвидо ван Россум рекомендует избегать любых использований `from <module> import ...` и размещать весь код внутри функций. Инициализация глобальных переменных и переменных класса должна использовать только константы или встроенные функции. Это означает, что всё из импортированного модуля должно ссылаться как `<module>.<name>`.14731474Джим Роскинд предлагает выполнять шаги в следующем порядке в каждом модуле:14751476- экспорт (глобальные переменные, функции и классы, которым не нужны импортированные базовые классы)1477- инструкции `import`1478- активный код (включая глобальные переменные, инициализируемые из импортированных значений).14791480ван Россуму такой подход не очень нравится, потому что импорты оказываются в странном месте, но это работает.14811482Маттиас Урлихс рекомендует перестроить код так, чтобы рекурсивный импорт вообще не требовался.14831484Эти решения не являются взаимоисключающими.14851486### [\_\_import\_\_(‘x.y.z’) возвращает \<module ‘x’\>; как получить z?](https://python-all.ru/3.7/faq/programming.html#id68)14871488Рассмотрите возможность использования удобной функции [`import_module()`](https://python-all.ru/3.7/library/importlib.html#importlib.import_module) из [`importlib`](https://python-all.ru/3.7/library/importlib.html#module-importlib) вместо этого.14891490```python1491z = importlib.import_module('x.y.z')1492```14931494### [Когда я редактирую импортированный модуль и повторно импортирую его, изменения не отображаются. Почему это происходит?](https://python-all.ru/3.7/faq/programming.html#id69)14951496Из соображений эффективности и согласованности Python читает файл модуля только при первом импорте модуля. Если бы это было не так, в программе, состоящей из многих модулей, каждый из которых импортирует один и тот же базовый модуль, этот базовый модуль разбирался бы и переразбирался много раз. Чтобы принудительно перечитать изменённый модуль, сделайте следующее:14971498```python1499import importlib1500import modname1501importlib.reload(modname)1502```15031504Предупреждение: этот метод не является абсолютно надёжным. В частности, модули, содержащие операторы типа15051506```python1507from modname import some_objects1508```15091510будут продолжать работать со старой версией импортированных объектов. Если модуль содержит определения классов, существующие экземпляры классов *не* будут обновлены для использования нового определения класса. Это может привести к следующему парадоксальному поведению:15111512```python1513>>> import importlib1514>>> import cls1515>>> c = cls.C()                # Создать экземпляр C1516>>> importlib.reload(cls)1517<module 'cls' from 'cls.py'>1518>>> isinstance(c, cls.C)       # isinstance ложно?!?1519False1520```15211522Суть проблемы становится ясна, если вывести «идентичность» объектов классов:15231524```python1525>>> hex(id(c.__class__))1526'0x7352a0'1527>>> hex(id(cls.C))1528'0x4198d0'1529```1530