Spec-Zone.ru › Python 3.12

Модель данных

3.1. Объекты, значения и типы

Объекты — это абстракция данных в Python. Все данные в программе на Python представлены объектами или отношениями между объектами. (В некотором смысле и в соответствии с моделью фон Неймана «компьютера с хранимой программой» код также представлен объектами.)

У каждого объекта есть идентичность, тип и значение. Идентичность объекта не меняется после его создания; можно считать её адресом объекта в памяти. Оператор is сравнивает идентичность двух объектов; функция id() возвращает целое число, представляющее его идентичность.

Подробности реализации CPython: В CPython id(x) — это адрес памяти, по которому хранится x.

Тип объекта определяет поддерживаемые им операции (например, «есть ли у него длина?»), а также возможные значения объектов этого типа. Функция type() возвращает тип объекта (который сам является объектом). Как и идентичность, тип объекта неизменяем. [1]

Значение некоторых объектов может меняться. Объекты, значение которых может меняться, называют изменяемыми; объекты, значение которых нельзя изменить после создания, называют неизменяемыми. (Значение неизменяемого контейнера, содержащего ссылку на изменяемый объект, может измениться, если изменится значение последнего; однако контейнер по-прежнему считается неизменяемым, поскольку набор содержащихся в нём объектов изменить нельзя. Таким образом, неизменяемость — не совсем то же самое, что неизменяемое значение; это более тонкое понятие.) Изменяемость объекта определяется его типом; например, числа, строки и кортежи неизменяемы, а словари и списки изменяемы.

Объекты никогда не уничтожаются явно; однако, когда на них больше нельзя сослаться, они могут быть удалены сборщиком мусора. Реализация может отложить сборку мусора или вовсе её не выполнять — качество реализации сборки мусора зависит от того, как она реализована, при условии что не удаляются объекты, на которые всё ещё можно сослаться.

Подробности реализации CPython: В настоящее время CPython использует подсчёт ссылок с (необязательным) отложенным обнаружением циклически связанных объектов-мусора. Этот механизм удаляет большинство объектов сразу после того, как на них больше нельзя сослаться, но не гарантирует удаление мусора, содержащего циклические ссылки. Сведения об управлении сборкой циклического мусора см. в документации модуля gc. Другие реализации работают иначе, и CPython может измениться. Не полагайтесь на немедленное окончательное удаление объектов, когда на них больше нельзя сослаться (поэтому файлы всегда следует закрывать явно).

Обратите внимание, что использование средств трассировки или отладки реализации может удерживать объекты, которые обычно можно было бы удалить. Также учтите, что перехват исключения с помощью оператора try…except может удерживать объекты.

Некоторые объекты содержат ссылки на «внешние» ресурсы, например открытые файлы или окна. Предполагается, что эти ресурсы освобождаются при сборке объекта мусором, но, поскольку сборка мусора не гарантируется, такие объекты также предоставляют явный способ освободить внешний ресурс — обычно метод close(). Настоятельно рекомендуется явно закрывать такие объекты. Для этого удобно использовать оператор try…finally или оператор with.

Некоторые объекты содержат ссылки на другие объекты; их называют контейнерами. Примеры контейнеров — кортежи, списки и словари. Ссылки являются частью значения контейнера. В большинстве случаев, говоря о значении контейнера, мы имеем в виду значения, а не идентичности содержащихся в нём объектов; однако, говоря об изменяемости контейнера, мы имеем в виду только идентичности непосредственно содержащихся в нём объектов. Поэтому значение неизменяемого контейнера (например, кортежа), содержащего ссылку на изменяемый объект, меняется при изменении этого изменяемого объекта.

Типы влияют почти на все аспекты поведения объектов. В некотором смысле они влияют даже на важность идентичности объекта: для неизменяемых типов операции, вычисляющие новые значения, могут возвращать ссылку на любой существующий объект того же типа и со значением, тогда как для изменяемых объектов это недопустимо. Например, после a = 1; b = 1 a и b могут ссылаться как на один и тот же объект со значением один, так и на разные объекты — в зависимости от реализации. Это объясняется тем, что int — неизменяемый тип, поэтому ссылку на 1 можно использовать повторно. Такое поведение зависит от используемой реализации, поэтому на него не следует полагаться, но о нём нужно помнить при использовании проверок идентичности объектов. Однако после c = []; d = [] гарантируется, что c и d будут ссылаться на два разных, уникальных, только что созданных пустых списка. (Обратите внимание, что e = f = [] присваивает один и тот же объект и e, и f.)

3.2. Стандартная иерархия типов

Ниже приведён список типов, встроенных в Python. Модули расширения (написанные на C, Java или других языках — в зависимости от реализации) могут определять дополнительные типы. В будущих версиях Python могут появиться новые типы в иерархии (например, рациональные числа, эффективно хранящиеся массивы целых чисел и т. д.), хотя такие дополнения часто будут предоставляться через стандартную библиотеку.

Некоторые приведённые ниже описания типов содержат абзац со списком «специальных атрибутов». Эти атрибуты предоставляют доступ к реализации и не предназначены для общего использования. Их определение может измениться в будущем.

3.2.1. None

У этого типа только одно значение. Существует единственный объект с этим значением. Доступ к этому объекту осуществляется через встроенное имя None. Во многих ситуациях оно используется для обозначения отсутствия значения, например возвращается функциями, которые явно ничего не возвращают. Его логическое значение — ложь.

3.2.2. NotImplemented

У этого типа только одно значение. Существует единственный объект с этим значением. Доступ к этому объекту осуществляется через встроенное имя NotImplemented. Числовые методы и методы расширенного сравнения должны возвращать это значение, если они не реализуют операцию для переданных операндов. (В зависимости от оператора интерпретатор тогда попробует обратную операцию или какой-либо другой вариант.) Это значение не следует использовать в логическом контексте.

Подробнее см. раздел Реализация арифметических операций.

Изменено в версии 3.9: Использование NotImplemented в логическом контексте считается устаревшим. Сейчас оно вычисляется как истина, но при этом выдаётся предупреждение DeprecationWarning. В будущей версии Python будет вызываться исключение TypeError.

3.2.3. Ellipsis

У этого типа только одно значение. Существует единственный объект с этим значением. Доступ к этому объекту осуществляется через литерал ... или встроенное имя Ellipsis. Его логическое значение — истина.

3.2.4. numbers.Number

Числа создаются числовыми литералами и возвращаются в качестве результатов арифметических операторов и встроенных арифметических функций. Числовые объекты неизменяемы: после создания их значение никогда не меняется. Числа Python, разумеется, тесно связаны с математическими числами, но на них распространяются ограничения числового представления в компьютерах.

Строковые представления числовых классов, вычисляемые методами __repr__() и __str__(), обладают следующими свойствами:

  • Это допустимые числовые литералы, которые при передаче конструктору соответствующего класса создают объект со значением исходного числа.
  • По возможности представление задаётся в десятичной системе счисления.
  • Начальные нули не отображаются, за исключением, возможно, одного нуля перед десятичной точкой.
  • Конечные нули не отображаются, за исключением, возможно, одного нуля после десятичной точки.
  • Знак отображается только для отрицательных чисел.

Python различает целые числа, числа с плавающей точкой и комплексные числа:

3.2.4.1. numbers.Integral

Они представляют элементы математического множества целых чисел (положительных и отрицательных).

Примечание

Правила представления целых чисел призваны обеспечить наиболее осмысленную интерпретацию операций сдвига и маскирования, выполняемых над отрицательными целыми числами.

Существует два типа целых чисел:

Integers (int)

Они представляют числа в неограниченном диапазоне, ограниченном только доступной (виртуальной) памятью. Для операций сдвига и маскирования предполагается двоичное представление, а отрицательные числа представлены разновидностью дополнительного кода, создающей иллюзию бесконечной строки знаковых битов, продолжающейся влево.

Booleans (bool)

Они представляют логические значения False и True. Единственными логическими объектами являются два объекта, представляющие значения False и True. Логический тип является подтипом целочисленного типа, и почти во всех контекстах логические значения ведут себя соответственно как 0 и 1; исключение составляет преобразование в строку, при котором возвращаются строки "False" и "True" соответственно.

3.2.4.2. numbers.Real (float)

Они представляют числа с плавающей точкой двойной точности на уровне машины. Допустимый диапазон и обработка переполнения зависят от архитектуры компьютера (а также от реализации на C или Java). Python не поддерживает числа с плавающей точкой одинарной точности: экономия процессорных ресурсов и памяти, обычно являющаяся причиной их использования, ничтожна по сравнению с накладными расходами на работу с объектами в Python, поэтому усложнять язык двумя видами чисел с плавающей точкой нет смысла.

3.2.4.3. numbers.Complex (complex)

Они представляют комплексные числа в виде пары чисел с плавающей точкой двойной точности на уровне машины. К ним применимы те же предостережения, что и к числам с плавающей точкой. Вещественную и мнимую части комплексного числа z можно получить с помощью атрибутов только для чтения z.real и z.imag.

3.2.5. Последовательности

Они представляют конечные упорядоченные наборы, индексируемые неотрицательными числами. Встроенная функция len() возвращает количество элементов последовательности. Если длина последовательности равна n, набор индексов содержит числа от 0 до n-1. Элемент i последовательности a выбирается с помощью a[i]. Некоторые последовательности, в том числе встроенные, интерпретируют отрицательные индексы, прибавляя к ним длину последовательности. Например, a[-2] равен a[n-2] — предпоследнему элементу последовательности a длины n.

Последовательности также поддерживают срезы: a[i:j] выбирает все элементы с индексом k, для которого выполняется i <= k < j. При использовании в качестве выражения срез представляет собой последовательность того же типа. Примечание выше об отрицательных индексах также относится к отрицательным позициям среза.

Некоторые последовательности также поддерживают «расширенную нарезку» с третьим параметром «шага»: a[i:j:k] выбирает все элементы a с индексом x, для которого выполняются условия x = i + n*k, n >= 0 и i <= x < j.

Последовательности различаются по изменяемости:

3.2.5.1. Неизменяемые последовательности

Объект неизменяемого типа последовательности нельзя изменить после его создания. (Если объект содержит ссылки на другие объекты, эти объекты могут быть изменяемыми и могут меняться; однако набор объектов, на которые непосредственно ссылается неизменяемый объект, изменить нельзя.)

К неизменяемым последовательностям относятся следующие типы:

Строки

Строка — это последовательность значений, представляющих кодовые точки Unicode. В строке можно представить все кодовые точки диапазона U+0000 - U+10FFFF. В Python нет типа char; вместо этого каждая кодовая точка строки представлена строковым объектом длины 1. Встроенная функция ord() преобразует кодовую точку из строкового представления в целое число диапазона 0 - 10FFFF; функция chr() преобразует целое число диапазона 0 - 10FFFF в соответствующий строковый объект длины 1. Метод str.encode() позволяет преобразовать str в bytes с использованием заданной кодировки текста, а метод bytes.decode() выполняет обратное преобразование.

Кортежи

Элементами кортежа могут быть произвольные объекты Python. Кортежи из двух или более элементов образуются списками выражений, разделённых запятыми. Кортеж из одного элемента («одноэлементный кортеж») можно создать, добавив запятую после выражения (само по себе выражение не создаёт кортеж, поскольку круглые скобки должны использоваться для группировки выражений). Пустой кортеж можно создать пустой парой круглых скобок.

Байты

Объект bytes — это неизменяемый массив. Его элементы — 8-битные байты, представленные целыми числами в диапазоне 0 <= x < 256. Для создания объектов bytes можно использовать байтовые литералы (например, b'abc') и встроенный конструктор bytes(). Кроме того, объекты bytes можно декодировать в строки с помощью метода decode().

3.2.5.2. Изменяемые последовательности

Изменяемые последовательности можно менять после создания. Обозначения индекса и среза можно использовать в качестве цели присваивания и в операторах del (удаления).

Примечание

Дополнительные примеры изменяемых типов последовательностей приведены в модулях collections и array.

В настоящее время существует два встроенных изменяемых типа последовательностей:

Списки

Элементами списка могут быть произвольные объекты Python. Списки образуются заключением списка выражений, разделённых запятыми, в квадратные скобки. (Обратите внимание: для создания списков длиной 0 или 1 не требуется никаких особых случаев.)

Байтовые массивы

Объект bytearray — это изменяемый массив. Он создаётся встроенным конструктором bytearray(). Помимо изменяемости (и, следовательно, нехешируемости), байтовые массивы предоставляют тот же интерфейс и функциональность, что и неизменяемые объекты bytes.

3.2.6. Типы множеств

Они представляют неупорядоченные конечные множества уникальных неизменяемых объектов. Поэтому индексировать их нельзя. Однако по ним можно итерироваться, а встроенная функция len() возвращает количество элементов множества. Множества часто используют для быстрой проверки принадлежности, удаления дубликатов из последовательности и вычисления математических операций, таких как пересечение, объединение, разность и симметрическая разность.

Для элементов множества действуют те же правила неизменяемости, что и для ключей словаря. Обратите внимание, что числовые типы подчиняются обычным правилам числового сравнения: если два числа равны (например, 1 и 1.0), в множестве может содержаться только одно из них.

В настоящее время существует два встроенных типа множеств:

Множества

Они представляют изменяемые множества. Их создают встроенным конструктором set(), а затем изменяют с помощью нескольких методов, например add().

Неизменяемые множества

Они представляют неизменяемые множества. Их создают встроенным конструктором frozenset(). Поскольку frozenset неизменяем и хешируем, его можно использовать как элемент другого множества или как ключ словаря.

3.2.7. Отображения

Они представляют конечные наборы объектов, индексируемые произвольными наборами индексов. Обозначение индекса a[k] выбирает элемент отображения a, индексированный значением k; его можно использовать в выражениях и в качестве цели присваивания или операторов del. Встроенная функция len() возвращает количество элементов отображения.

В настоящее время существует один встроенный тип отображения:

3.2.7.1. Словари

Они представляют конечные наборы объектов, индексируемые почти произвольными значениями. В качестве ключей нельзя использовать только значения, содержащие списки, словари или другие изменяемые типы, сравниваемые по значению, а не по идентичности объекта: причина в том, что эффективная реализация словарей требует постоянства хеш-значения ключа. Числовые типы, используемые в качестве ключей, подчиняются обычным правилам числового сравнения: если два числа равны (например, 1 и 1.0), их можно взаимозаменяемо использовать для доступа к одной и той же записи словаря.

Словари сохраняют порядок вставки: ключи выдаются в том же порядке, в котором их последовательно добавляли в словарь. Замена существующего ключа не меняет порядок, однако удаление ключа и его повторное добавление перемещает его в конец, а не оставляет на прежнем месте.

Словари изменяемы; их можно создавать с помощью обозначения {} (см. раздел Отображения словарей).

Дополнительные примеры типов отображений представлены в модулях расширения dbm.ndbm и dbm.gnu, а также в модуле collections.

Изменено в версии 3.7: В версиях Python до 3.6 словари не сохраняли порядок вставки. В CPython 3.6 порядок вставки сохранялся, но в то время это считалось особенностью реализации, а не гарантией языка.

3.2.8. Вызываемые типы

Это типы, к которым можно применить операцию вызова функции (см. раздел Вызовы).

3.2.8.1. Функции, определённые пользователем

Объект функции, определённой пользователем, создаётся определением функции (см. раздел Определения функций). Его следует вызывать со списком аргументов, содержащим столько же элементов, сколько формальных параметров в списке параметров функции.

3.2.8.1.1. Специальные атрибуты только для чтения

Атрибут

Значение

function.__globals__

Ссылка на dictionary, содержащий глобальные переменные функции, — глобальное пространство имён модуля, в котором была определена функция.

function.__closure__

None или tuple ячеек, содержащих привязки для свободных переменных функции.

У объекта ячейки есть атрибут cell_contents. С его помощью можно получить значение ячейки, а также задать его.

3.2.8.1.2. Специальные атрибуты для записи

Для большинства этих атрибутов проверяется тип присваиваемого значения:

Атрибут

Значение

function.__doc__

Строка документации функции или None, если она отсутствует.

function.__name__

Имя функции. См. также: __name__ attributes.

function.__qualname__

Полное имя функции. См. также: __qualname__ attributes.

Добавлено в версии 3.3.

function.__module__

Имя модуля, в котором была определена функция, или None, если оно отсутствует.

function.__defaults__

tuple, содержащий значения по умолчанию для тех параметров, для которых они заданы, или None, если ни для одного параметра не задано значение по умолчанию.

function.__code__

Объект кода, представляющий скомпилированное тело функции.

function.__dict__

Пространство имён для произвольных атрибутов функции. См. также: __dict__ attributes.

function.__annotations__

dictionary, содержащий аннотации параметров. Ключами словаря являются имена параметров, а для аннотации возвращаемого значения используется 'return', если она задана. См. также: Рекомендации по использованию аннотаций.

function.__kwdefaults__

dictionary, содержащий значения по умолчанию для параметров, доступных только по ключевому слову.

function.__type_params__

tuple, содержащий параметры типов обобщённой функции.

Добавлено в версии 3.12.

Объекты функций также поддерживают получение и установку произвольных атрибутов, которые можно использовать, например, для прикрепления к функциям метаданных. Для получения и установки таких атрибутов используется обычная точечная нотация атрибутов.

Особенность реализации CPython: Текущая реализация CPython поддерживает атрибуты функций только для функций, определённых пользователем. В будущем может появиться поддержка атрибутов у встроенных функций.

Дополнительные сведения об определении функции можно получить из её объекта кода (доступного через атрибут __code__).

3.2.8.2. Методы экземпляров

Объект метода экземпляра объединяет класс, экземпляр класса и любой вызываемый объект (обычно функцию, определённую пользователем).

Специальные атрибуты только для чтения:

method.__self__

Ссылка на объект экземпляра класса, к которому привязан метод

method.__func__

Ссылка на исходный объект функции

method.__doc__

Документация метода (совпадает с method.__func__.__doc__). Объект string, если у исходной функции была строка документации, иначе None.

method.__name__

Имя метода (совпадает с method.__func__.__name__)

method.__module__

Имя модуля, в котором был определён метод, или None, если оно отсутствует.

Методы также поддерживают доступ (но не установку) к произвольным атрибутам функции, принадлежащим лежащему в их основе объекту функции.

Объекты методов, определённых пользователем, могут создаваться при получении атрибута класса (возможно, через экземпляр этого класса), если этот атрибут является объектом функции, определённой пользователем, или объектом classmethod.

Когда объект метода экземпляра создаётся при получении из класса через один из его экземпляров объекта функции, определённой пользователем, его атрибут __self__ содержит экземпляр, а сам объект метода считается привязанным. Атрибут __func__ нового метода содержит исходный объект функции.

Когда объект метода экземпляра создаётся при получении объекта classmethod из класса или экземпляра, его атрибут __self__ содержит сам класс, а атрибут __func__ — объект функции, лежащий в основе метода класса.

При вызове объекта метода экземпляра вызывается лежащая в его основе функция (__func__), при этом экземпляр класса (__self__) вставляется в начало списка аргументов. Например, если C — это класс, содержащий определение функции f(), а x — экземпляр C, то вызов x.f(1) эквивалентен вызову C.f(x, 1).

Если объект метода экземпляра получен из объекта classmethod, «экземпляром класса», хранящимся в __self__, фактически будет сам класс, поэтому вызов x.f(1) или C.f(1) эквивалентен вызову f(C,1), где f — лежащая в основе функция.

Важно отметить, что функции, определённые пользователем и являющиеся атрибутами экземпляра класса, не преобразуются в привязанные методы; это происходит только в том случае, если функция является атрибутом класса.

3.2.8.3. Функции-генераторы

Функция или метод, в котором используется инструкция yield (см. раздел Инструкция yield), называется функцией-генератором. При вызове такая функция всегда возвращает объект итератора, который можно использовать для выполнения тела функции: вызов метода iterator.__next__() итератора приводит к выполнению функции до тех пор, пока она не выдаст значение с помощью инструкции yield. Когда функция выполняет инструкцию return или достигает конца, возбуждается исключение StopIteration, и итератор достигает конца последовательности возвращаемых значений.

3.2.8.4. Функции-корутины

Функция или метод, определённые с помощью async def, называются функцией-корутиной. При вызове такая функция возвращает объект корутины. Она может содержать выражения await, а также инструкции async with и async for. См. также раздел Объекты корутин.

3.2.8.5. Асинхронные функции-генераторы

Функция или метод, определённые с помощью async def и использующие инструкцию yield, называются асинхронной функцией-генератором. При вызове такая функция возвращает объект асинхронного итератора, который можно использовать в инструкции async for для выполнения тела функции.

Вызов метода aiterator.__anext__ асинхронного итератора возвращает объект ожидаемого объекта, который при ожидании выполняется до тех пор, пока не выдаст значение с помощью выражения yield. Когда функция выполняет пустую инструкцию return или достигает конца, возбуждается исключение StopAsyncIteration, и асинхронный итератор достигает конца последовательности выдаваемых значений.

3.2.8.6. Встроенные функции

Объект встроенной функции — это обёртка над функцией C. Примерами встроенных функций являются len() и math.sin() (math — стандартный встроенный модуль). Количество и тип аргументов определяются функцией C. Специальные атрибуты только для чтения:

  • __doc__ — строка документации функции или None, если она отсутствует. См. function.__doc__.
  • __name__ — имя функции. См. function.__name__.
  • __self__ имеет значение None (см. следующий пункт).
  • __module__ — имя модуля, в котором была определена функция, или None, если оно отсутствует. См. function.__module__.

3.2.8.7. Встроенные методы

По сути, это другая форма представления встроенной функции, которая в данном случае содержит объект, передаваемый функции C как неявный дополнительный аргумент. Примером встроенного метода является alist.append(), если предположить, что alist — объект списка. В этом случае специальный атрибут только для чтения __self__ указывает на объект, обозначенный именем alist. (Этот атрибут имеет ту же семантику, что и other instance methods.)

3.2.8.8. Классы

Классы являются вызываемыми объектами. Обычно они служат фабриками для создания собственных экземпляров, но для типов классов, переопределяющих __new__(), возможны и другие варианты. Аргументы вызова передаются в __new__() и, как правило, в __init__() для инициализации нового экземпляра.

3.2.8.9. Экземпляры классов

Экземпляры произвольных классов можно сделать вызываемыми, определив в их классе метод __call__().

3.2.9. Модули

Модули — это базовая организационная единица кода Python; они создаются системой импорта при вызове оператора import или таких функций, как importlib.import_module() и встроенная функция __import__(). Объект модуля имеет пространство имён, реализованное объектом dictionary (это словарь, на который ссылается атрибут __globals__ функций, определённых в модуле). Обращения к атрибутам преобразуются в поиск в этом словаре: например, m.x эквивалентно m.__dict__["x"]. Объект модуля не содержит объект кода, использованный для инициализации модуля (поскольку после завершения инициализации он не нужен).

Присваивание атрибуту обновляет словарь пространства имён модуля: например, m.x = 1 эквивалентно m.__dict__["x"] = 1.

3.2.9.1. Атрибуты объектов модулей, связанные с импортом

Объекты модулей имеют следующие атрибуты, связанные с системой импорта. При создании модуля с помощью механизмов системы импорта значения этих атрибутов определяются на основе спецификации модуля до того, как загрузчик выполнит загрузку модуля.

Для динамического создания модуля, а не с помощью системы импорта, рекомендуется использовать importlib.util.module_from_spec(): эта функция задаёт подходящие значения различным атрибутам, контролируемым механизмом импорта. Можно также создавать модули напрямую с помощью конструктора types.ModuleType, но этот способ более подвержен ошибкам: при таком подходе большинство атрибутов необходимо вручную задавать объекту модуля после его создания.

Внимание

За исключением __name__, настоятельно рекомендуется полагаться на __spec__ и его атрибуты, а не на другие отдельные атрибуты, перечисленные в этом подразделе. Обратите внимание: изменение атрибута у __spec__ не обновит соответствующий атрибут самого модуля:

>>> import typing
>>> typing.__name__, typing.__spec__.name
('typing', 'typing')
>>> typing.__spec__.name = 'spelling'
>>> typing.__name__, typing.__spec__.name
('typing', 'spelling')
>>> typing.__name__ = 'keyboard_smashing'
>>> typing.__name__, typing.__spec__.name
('keyboard_smashing', 'spelling')
module.__name__

Имя, используемое для уникальной идентификации модуля в системе импорта. Для непосредственно выполняемого модуля этому атрибуту будет присвоено значение "__main__".

Значением этого атрибута должно быть полное имя модуля. Предполагается, что оно совпадает со значением module.__spec__.name.

module.__spec__

Запись о состоянии модуля, связанном с системой импорта.

Равно объекту module spec, использованному при импорте модуля. Подробнее см. в разделе Спецификации модулей.

Добавлено в версии 3.4.

module.__package__

Пакет, к которому принадлежит модуль.

Если модуль является модулем верхнего уровня (то есть не входит в какой-либо конкретный пакет), атрибуту следует присвоить значение '' (пустую строку). В противном случае ему следует присвоить имя пакета модуля (которое может совпадать с module.__name__, если сам модуль является пакетом). Подробнее см. в PEP 366.

Этот атрибут используется вместо __name__ для вычисления явных относительных импортов главных модулей. Для модулей, динамически созданных с помощью конструктора types.ModuleType, по умолчанию он равен None; используйте вместо этого importlib.util.module_from_spec(), чтобы атрибуту было присвоено значение типа str.

Настоятельно рекомендуется использовать module.__spec__.parent вместо module.__package__. Теперь __package__ используется только как резервный вариант, если __spec__.parent не задан; этот резервный механизм объявлен устаревшим.

Изменено в версии 3.4: Теперь для модулей, динамически созданных с помощью конструктора types.ModuleType, значением этого атрибута по умолчанию является None. Ранее этот атрибут был необязательным.

Изменено в версии 3.6: Ожидается, что значение __package__ будет совпадать со значением __spec__.parent. Теперь __package__ используется только как резервный вариант при разрешении импорта, если __spec__.parent не определён.

Изменено в версии 3.10: Если при разрешении импорта используется __package__ вместо __spec__.parent, возникает исключение ImportWarning.

Изменено в версии 3.12: При использовании __package__ в качестве резервного варианта при разрешении импорта возникает исключение DeprecationWarning вместо ImportWarning.

module.__loader__

Объект загрузчика, использованный механизмом импорта для загрузки модуля.

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

Для модулей, динамически созданных с помощью конструктора types.ModuleType, значение __loader__ по умолчанию равно None; используйте вместо этого importlib.util.module_from_spec(), чтобы атрибуту было присвоено значение — объект загрузчика.

Настоятельно рекомендуется использовать module.__spec__.loader вместо module.__loader__.

Изменено в версии 3.4: Теперь для модулей, динамически созданных с помощью конструктора types.ModuleType, значением этого атрибута по умолчанию является None. Ранее этот атрибут был необязательным.

Устарело с версии 3.12, будет удалено в версии 3.16: Задавать __loader__ модулю, не задавая __spec__.loader, не рекомендуется. В Python 3.16 система импорта и стандартная библиотека перестанут задавать __loader__ и учитывать его.

module.__path__

Последовательность строк (возможно, пустая), перечисляющая расположения, в которых будут найдены подмодули пакета. У модулей, не являющихся пакетами, атрибута __path__ быть не должно. Подробнее см. в разделе Атрибуты __path__ у модулей.

Настоятельно рекомендуется использовать module.__spec__.submodule_search_locations вместо module.__path__.

module.__file__
module.__cached__

__file__ и __cached__ — необязательные атрибуты, которые могут быть заданы, а могут и отсутствовать. Если они заданы, оба атрибута должны иметь тип str.

__file__ указывает путь к файлу, из которого был загружен модуль (если он загружен из файла), или путь к файлу разделяемой библиотеки для модулей расширений, динамически загруженных из такой библиотеки. Для некоторых типов модулей этот атрибут может отсутствовать, например для модулей C, статически связанных с интерпретатором. Система импорта может не задавать его, если он не имеет семантического значения (например, для модуля, загруженного из базы данных).

Если задан __file__, может быть также задан атрибут __cached__ — путь к скомпилированной версии кода (например, к файлу байт-кода). Для задания этого атрибута наличие файла не обязательно: путь может указывать лишь на место, где скомпилированный файл находился бы (см. PEP 3147).

Обратите внимание, что __cached__ может быть задан, даже если __file__ не задан. Однако такая ситуация встречается довольно редко. В конечном счёте именно загрузчик использует спецификацию модуля, предоставленную поисковиком (на её основе формируются __file__ и __cached__). Поэтому такая нетипичная ситуация может быть уместна, если загрузчик умеет загружать модуль из кэша, но в остальных случаях не загружает его из файла.

Настоятельно рекомендуется использовать module.__spec__.cached вместо module.__cached__.

3.2.9.2. Другие записываемые атрибуты объектов модулей

Помимо перечисленных выше атрибутов, связанных с импортом, у объектов модулей есть следующие записываемые атрибуты:

module.__doc__

Строка документации модуля или None, если она отсутствует. См. также: __doc__ attributes.

module.__annotations__

Словарь с аннотациями переменных, собранными при выполнении тела модуля. Рекомендации по работе с __annotations__ см. в разделе Рекомендации по работе с аннотациями.

3.2.9.3. Словари модулей

У объектов модулей также есть следующий специальный атрибут только для чтения:

module.__dict__

Пространство имён модуля в виде объекта-словаря. В отличие от всех остальных перечисленных здесь атрибутов, __dict__ нельзя получить как глобальную переменную внутри модуля; к нему можно обратиться только как к атрибуту объекта модуля.

Особенность реализации CPython: Из-за особенностей очистки словарей модулей в CPython словарь модуля будет очищен, когда модуль выйдет из области видимости, даже если на словарь всё ещё существуют активные ссылки. Чтобы этого избежать, скопируйте словарь или сохраните модуль, пока используете его словарь напрямую.

3.2.10. Пользовательские классы

Пользовательские типы классов обычно создаются определениями классов (см. раздел Определения классов). У класса есть пространство имён, реализованное объектом-словарём. Обращения к атрибутам класса преобразуются в поиск в этом словаре: например, C.x преобразуется в C.__dict__["x"] (хотя существует ряд перехватчиков, позволяющих находить атрибуты другими способами). Если имя атрибута там не найдено, поиск продолжается в базовых классах. При поиске в базовых классах используется порядок разрешения методов C3, который корректно работает даже при наличии структур наследования типа «ромб», когда несколько путей наследования ведут к общему предку. Дополнительные сведения о MRO C3, используемом в Python, см. в разделе Порядок разрешения методов в Python 2.3.

Если обращение к атрибуту класса (например, класса C) возвращает объект метода класса, он преобразуется в объект метода экземпляра, атрибут __self__ которого равен C. Если оно возвращает объект staticmethod, то он преобразуется в объект, обёрнутый объектом статического метода. См. раздел Реализация дескрипторов — там описан ещё один способ, которым атрибуты, полученные из класса, могут отличаться от тех, что фактически содержатся в его __dict__.

Присваивание атрибутов класса обновляет словарь класса, но никогда не словарь базового класса.

Объект класса можно вызвать (см. выше), чтобы получить экземпляр класса (см. ниже).

3.2.10.1. Специальные атрибуты

Атрибут

Значение

type.__name__

Имя класса. См. также: __name__ attributes.

type.__qualname__

Квалифицированное имя класса. См. также: __qualname__ attributes.

type.__module__

Имя модуля, в котором был определён класс.

type.__dict__

Объект mapping proxy, предоставляющий доступ только для чтения к пространству имён класса. См. также: __dict__ attributes.

type.__bases__

Объект tuple, содержащий базовые классы данного класса. В большинстве случаев для класса, определённого как class X(A, B, C), значение X.__bases__ будет в точности равно (A, B, C).

type.__doc__

Строка документации класса или None, если она не определена. Подклассы не наследуют этот атрибут.

type.__annotations__

Словарь с аннотациями переменных, собранными при выполнении тела класса. Рекомендации по работе с __annotations__ см. в разделе Рекомендации по работе с аннотациями.

Внимание

Прямой доступ к атрибуту __annotations__ объекта класса может привести к неверным результатам при наличии метаклассов. Кроме того, у некоторых классов этот атрибут может отсутствовать. Для безопасного получения аннотаций класса используйте inspect.get_annotations().

type.__type_params__

Объект tuple, содержащий параметры типов обобщённого класса.

Добавлено в версии 3.12.

type.__mro__

Объект tuple, содержащий классы, которые учитываются при поиске базовых классов во время разрешения методов.

3.2.10.2. Специальные методы

Помимо описанных выше специальных атрибутов, у всех классов Python также доступны следующие два метода:

type.mro()

Метакласс может переопределить этот метод, чтобы настроить порядок разрешения методов для его экземпляров. Он вызывается при создании экземпляра класса, а его результат сохраняется в __mro__.

type.__subclasses__()

Каждый класс хранит список слабых ссылок на свои непосредственные подклассы. Этот метод возвращает список всех ещё действующих ссылок. Список упорядочен по порядку определения. Пример:

>>> class A: pass
>>> class B(A): pass
>>> A.__subclasses__()
[<class 'B'>]

3.2.11. Экземпляры классов

Экземпляр класса создаётся вызовом объекта класса (см. выше). Пространство имён экземпляра класса реализовано в виде словаря, в котором в первую очередь выполняется поиск при обращении к атрибутам. Если атрибут там не найден, но у класса экземпляра есть атрибут с таким именем, поиск продолжается среди атрибутов класса. Если найденный атрибут класса является объектом определённой пользователем функции, он преобразуется в объект метода экземпляра, атрибут __self__ которого содержит экземпляр. Объекты статических методов и методов класса также преобразуются; см. выше раздел «Классы». См. раздел Реализация дескрипторов — там описан ещё один способ, которым атрибуты класса, полученные через его экземпляры, могут отличаться от объектов, фактически хранящихся в __dict__ класса. Если атрибут класса не найден, а у класса объекта есть метод __getattr__(), он вызывается для выполнения поиска.

Присваивание атрибутов и их удаление обновляют словарь экземпляра, но никогда словарь класса. Если у класса есть метод __setattr__() или __delattr__(), вместо непосредственного обновления словаря экземпляра вызывается этот метод.

Экземпляры классов могут вести себя как числа, последовательности или отображения, если у них есть методы с определёнными специальными именами. См. раздел Специальные имена методов.

3.2.11.1. Специальные атрибуты

object.__class__

Класс, которому принадлежит экземпляр класса.

object.__dict__

Словарь или другой объект-отображение, используемый для хранения (изменяемых) атрибутов объекта. Атрибут __dict__ есть не у всех экземпляров; подробнее см. в разделе __slots__.

3.2.12. Объекты ввода-вывода (также называемые файловыми объектами)

Файловый объект представляет открытый файл. Для создания файловых объектов доступны различные способы: встроенная функция open(), а также os.popen(), os.fdopen() и метод makefile() объектов сокетов (а также, возможно, другие функции или методы, предоставляемые модулями расширений).

Объекты sys.stdin, sys.stdout и sys.stderr инициализируются файловыми объектами, соответствующими стандартным потокам ввода, вывода и ошибок интерпретатора; все они открыты в текстовом режиме и поэтому соответствуют интерфейсу, определённому абстрактным классом io.TextIOBase.

3.2.13. Внутренние типы

Пользователю доступны некоторые типы, используемые интерпретатором внутри. Их определения могут измениться в будущих версиях интерпретатора, но для полноты они упомянуты здесь.

3.2.13.1. Объекты кода

Объекты кода представляют скомпилированный в байт-код исполняемый код Python, или байт-код. Различие между объектом кода и объектом функции состоит в том, что объект функции содержит явную ссылку на глобальные переменные функции (модуль, в котором она была определена), а объект кода не содержит контекста; кроме того, значения аргументов по умолчанию хранятся в объекте функции, а не в объекте кода (поскольку они представляют значения, вычисленные во время выполнения). В отличие от объектов функций, объекты кода неизменяемы и не содержат ссылок (прямых или косвенных) на изменяемые объекты.

3.2.13.1.1. Специальные атрибуты только для чтения
codeobject.co_name

Имя функции

codeobject.co_qualname

Полное имя функции

Добавлено в версии 3.11.

codeobject.co_argcount

Общее количество позиционных параметров функции (включая параметры, допускающие только позиционную передачу, и параметры со значениями по умолчанию)

codeobject.co_posonlyargcount

Количество параметров функции, допускающих только позиционную передачу (включая аргументы со значениями по умолчанию)

codeobject.co_kwonlyargcount

Количество параметров функции, допускающих только передачу по ключевому слову (включая аргументы со значениями по умолчанию)

codeobject.co_nlocals

Количество локальных переменных, используемых функцией (включая параметры)

codeobject.co_varnames

tuple, содержащий имена локальных переменных функции (начиная с имён параметров)

codeobject.co_cellvars

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

codeobject.co_freevars

tuple, содержащий имена свободных переменных функции

codeobject.co_code

Строка, представляющая последовательность инструкций байт-кода в функции

codeobject.co_consts

tuple, содержащий литералы, используемые байт-кодом функции

codeobject.co_names

tuple, содержащий имена, используемые байт-кодом функции

codeobject.co_filename

Имя файла, из которого был скомпилирован код

codeobject.co_firstlineno

Номер первой строки функции

codeobject.co_lnotab

Строка, кодирующая соответствие смещений байт-кода номерам строк. Подробности см. в исходном коде интерпретатора.

Устарело с версии 3.12: Этот атрибут объектов кода устарел и может быть удалён в Python 3.15.

codeobject.co_stacksize

Требуемый размер стека для объекта кода

codeobject.co_flags

integer, кодирующее набор флагов интерпретатора.

Для co_flags определены следующие биты флагов: бит 0x04 установлен, если функция использует синтаксис *arguments для приёма произвольного количества позиционных аргументов; бит 0x08 установлен, если функция использует синтаксис **keywords для приёма произвольных аргументов, передаваемых по ключевым словам; бит 0x20 установлен, если функция является генератором. Подробное описание семантики каждого возможного флага см. в разделе Битовые флаги объектов кода.

Объявления будущих возможностей (from __future__ import division) также используют биты в co_flags, указывая, был ли объект кода скомпилирован с включённой определённой возможностью: бит 0x2000 установлен, если функция была скомпилирована с включённым делением из будущих версий; биты 0x10 и 0x1000 использовались в более ранних версиях Python.

Другие биты в co_flags зарезервированы для внутреннего использования.

Если объект кода представляет функцию, первым элементом в co_consts является строка документации функции или None, если она не определена.

3.2.13.1.2. Методы объектов кода
codeobject.co_positions()

Возвращает итерируемый объект с позициями в исходном коде для каждой инструкции байт-кода в объекте кода.

Итератор возвращает tuple, содержащие (start_line, end_line, start_column, end_column). i-й кортеж соответствует позиции в исходном коде, из которой была скомпилирована i-я единица кода. Нумерация столбцов начинается с 0; значения указаны в смещениях байтов utf-8 для соответствующей строки исходного кода.

Эти позиционные данные могут отсутствовать. Ниже приведён неполный список случаев, когда это возможно:

  • Запуск интерпретатора с параметром -X no_debug_ranges.
  • Загрузка файла pyc, скомпилированного с использованием параметра -X no_debug_ranges.
  • Кортежи позиций, соответствующие искусственным инструкциям.
  • Номера строк и столбцов, которые невозможно представить из-за ограничений конкретной реализации.

В этом случае некоторые или все элементы кортежа могут быть равны None.

Добавлено в версии 3.11.

Примечание

Для этой возможности требуется хранить позиции столбцов в объектах кода, что может немного увеличить размер скомпилированных файлов Python на диске или объём используемой интерпретатором памяти. Чтобы не сохранять дополнительные данные и/или отключить вывод дополнительной информации в трассировке стека, можно использовать флаг командной строки -X no_debug_ranges или переменную окружения PYTHONNODEBUGRANGES.

codeobject.co_lines()

Возвращает итератор, который выдаёт сведения о последовательных диапазонах байт-кода. Каждый выдаваемый элемент — это кортеж (start, end, lineno) tuple:

  • start (значение типа int) представляет смещение (включительно) начала диапазона байт-кода
  • end (значение типа int) представляет смещение (не включительно) конца диапазона байт-кода
  • lineno — это значение типа int, представляющее номер строки диапазона байт-кода, или None, если у байт-кода в данном диапазоне нет номера строки

Выдаваемые элементы обладают следующими свойствами:

  • Первый выданный диапазон будет иметь значение start, равное 0.
  • Диапазоны (start, end) будут неубывающими и непрерывными. То есть для любой пары tuple значение start второго будет равно значению end первого.
  • Ни один диапазон не будет обратным: end >= start для всех троек.
  • У последнего выданного tuple значение end будет равно размеру байт-кода.

Допускаются диапазоны нулевой ширины, для которых start == end. Диапазоны нулевой ширины используются для строк, присутствующих в исходном коде, но удалённых компилятором байт-кода.

Добавлено в версии 3.10.

См. также

PEP 626 — Точные номера строк для отладки и других инструментов.

PEP, в котором был введён метод co_lines().

codeobject.replace(**kwargs)

Возвращает копию объекта кода с новыми значениями для указанных полей.

Добавлено в версии 3.8.

3.2.13.2. Объекты кадров

Объекты кадров представляют кадры выполнения. Они могут встречаться в объектах трассировки стека, а также передаются зарегистрированным функциям трассировки.

3.2.13.2.1. Специальные атрибуты только для чтения
frame.f_back

Указывает на предыдущий кадр стека (в сторону вызывающего кода) или None, если это нижний кадр стека

frame.f_code

Объект кода, выполняемый в этом кадре. Доступ к этому атрибуту вызывает событие аудита object.__getattr__ с аргументами obj и "f_code".

frame.f_locals

Словарь, используемый кадром для поиска локальных переменных

frame.f_globals

Словарь, используемый кадром для поиска глобальных переменных

frame.f_builtins

Словарь, используемый кадром для поиска встроенных (предопределённых) имён

frame.f_lasti

«Точная инструкция» объекта кадра (это индекс в строке байт-кода объекта кода)

3.2.13.2.2. Специальные атрибуты для записи
frame.f_trace

Если значение не равно None, это функция, вызываемая при различных событиях во время выполнения кода (она используется отладчиками). Обычно событие возникает для каждой новой строки исходного кода (см. f_trace_lines).

frame.f_trace_lines

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

frame.f_trace_opcodes

Установите этому атрибуту значение True, чтобы разрешить запрос событий для каждой операции. Обратите внимание, что это может привести к неопределённому поведению интерпретатора, если исключения, возбуждённые функцией трассировки, выйдут за пределы трассируемой функции.

frame.f_lineno

Текущий номер строки кадра — запись в этот атрибут из функции трассировки приводит к переходу на указанную строку (только для самого нижнего кадра). Отладчик может реализовать команду перехода (она же Set Next Statement), записывая значение в этот атрибут.

3.2.13.2.3. Методы объектов кадров

Объекты кадров поддерживают один метод:

frame.clear()

Этот метод удаляет все ссылки на локальные переменные, удерживаемые кадром. Кроме того, если кадр принадлежал генератору, генератор завершается. Это помогает разрывать циклы ссылок с участием объектов кадров (например, при перехвате исключения и сохранении его трассировки стека для последующего использования).

Если кадр в данный момент выполняется, возникает исключение RuntimeError.

Добавлено в версии 3.4.

3.2.13.3. Объекты трассировки стека

Объекты трассировки стека представляют трассировку стека исключения. Объект трассировки стека неявно создаётся при возникновении исключения; его также можно создать явно, вызвав types.TracebackType.

Изменено в версии 3.7: Теперь объекты трассировки стека можно явно создавать из кода Python.

Для неявно созданных трассировок, когда при поиске обработчика исключения происходит раскрутка стека выполнения, на каждом пройденном уровне объект трассировки стека добавляется в начало текущей трассировки. При входе в обработчик исключения трассировка стека становится доступной программе. (См. раздел Инструкция try.) Она доступна как третий элемент кортежа, возвращаемого sys.exc_info(), и как атрибут __traceback__ перехваченного исключения.

Если в программе нет подходящего обработчика, трассировка стека записывается (в удобочитаемом формате) в стандартный поток ошибок; если интерпретатор работает в интерактивном режиме, она также становится доступна пользователю как sys.last_traceback.

Для явно созданных трассировок создатель определяет, как следует связывать атрибуты tb_next, чтобы сформировать полную трассировку стека.

Специальные атрибуты только для чтения:

traceback.tb_frame

Указывает на кадр выполнения текущего уровня.

Доступ к этому атрибуту вызывает событие аудита object.__getattr__ с аргументами obj и "tb_frame".

traceback.tb_lineno

Возвращает номер строки, в которой произошло исключение

traceback.tb_lasti

Указывает на «точную инструкцию».

Номер строки и последняя инструкция в трассировке стека могут отличаться от номера строки соответствующего объекта кадра, если исключение возникло в инструкции try без соответствующей ветви except или с ветвью finally.

traceback.tb_next

Специальный атрибут для записи tb_next указывает на следующий уровень трассировки стека (в сторону кадра, в котором произошло исключение) или равен None, если следующего уровня нет.

Изменено в версии 3.7: Теперь в этот атрибут можно записывать значения

3.2.13.4. Объекты среза

Объекты среза используются для представления срезов в методах __getitem__(). Они также создаются встроенной функцией slice().

Специальные атрибуты только для чтения: start — нижняя граница; stop — верхняя граница; step — шаг; если атрибут не указан, его значение равно None. Эти атрибуты могут иметь любой тип.

Объекты среза поддерживают один метод:

slice.indices(self, length)

Этот метод принимает единственный целочисленный аргумент length и вычисляет информацию о срезе, который описывал бы данный объект среза при применении к последовательности из length элементов. Метод возвращает кортеж из трёх целых чисел: соответственно индексы start и stop, а также step — шаг среза. Отсутствующие индексы и индексы за пределами последовательности обрабатываются так же, как и в обычных срезах.

3.2.13.5. Объекты статических методов

Объекты статических методов позволяют предотвратить описанное выше преобразование объектов функций в объекты методов. Объект статического метода — это обёртка над любым другим объектом, обычно над объектом метода, определённого пользователем. При получении объекта статического метода из класса или экземпляра класса фактически возвращается обёрнутый объект, который больше не подвергается никаким преобразованиям. Объекты статических методов также являются вызываемыми. Они создаются встроенным конструктором staticmethod().

3.2.13.6. Объекты методов класса

Объект метода класса, как и объект статического метода, представляет собой обёртку над другим объектом, изменяющую способ получения этого объекта из классов и экземпляров классов. Поведение объектов методов класса при таком получении описано выше, в разделе «методы экземпляра». Объекты методов класса создаются встроенным конструктором classmethod().

3.3. Специальные имена методов

Класс может реализовать определённые операции, вызываемые специальным синтаксисом (например, арифметические операции, индексирование и срезы), определяя методы со специальными именами. Так в Python реализована перегрузка операторов, позволяющая классам задавать собственное поведение при использовании операторов языка. Например, если класс определяет метод с именем __getitem__(), а x — экземпляр этого класса, то x[i] примерно эквивалентно type(x).__getitem__(x, i). Если не указано иное, попытки выполнить операцию приводят к исключению, если соответствующий метод не определён (обычно AttributeError или TypeError).

Установка специального метода в None указывает, что соответствующая операция недоступна. Например, если класс устанавливает __iter__() в None, класс не является итерируемым, поэтому вызов iter() для его экземпляров вызовет TypeError (без перехода к __getitem__()). [2]

При реализации класса, имитирующего любой встроенный тип, важно реализовывать имитацию только в той мере, в какой это имеет смысл для моделируемого объекта. Например, некоторые последовательности могут поддерживать получение отдельных элементов, но извлечение среза для них может быть бессмысленным. (Один из таких примеров — интерфейс NodeList в объектной модели документов W3C.)

3.3.1. Основная настройка

object.__new__(cls[, ...])

Вызывается для создания нового экземпляра класса cls. __new__() — статический метод (обрабатывается особым образом, поэтому объявлять его как статический не требуется), первым аргументом которого является класс, экземпляр которого запрошен. Остальные аргументы передаются в выражение-конструктор объекта (вызов класса). Возвращаемым значением __new__() должен быть новый экземпляр объекта (обычно экземпляр cls).

Типичные реализации создают новый экземпляр класса, вызывая метод __new__() суперкласса с помощью super().__new__(cls[, ...]) и подходящими аргументами, а затем при необходимости изменяя созданный экземпляр перед его возвратом.

Если __new__() вызывается во время создания объекта и возвращает экземпляр cls, то будет вызван метод __init__() нового экземпляра, как в __init__(self[, ...]), где self — новый экземпляр, а остальные аргументы совпадают с переданными конструктору объекта.

Если __new__() не возвращает экземпляр cls, метод __init__() нового экземпляра вызван не будет.

__new__() предназначен главным образом для настройки создания экземпляров подклассами неизменяемых типов (таких как int, str или tuple). Его также часто переопределяют в пользовательских метаклассах для настройки создания классов.

object.__init__(self[, ...])

Вызывается после создания экземпляра (методом __new__()), но до его возврата вызывающему коду. Аргументы совпадают с переданными выражению-конструктору класса. Если базовый класс содержит метод __init__(), метод __init__() производного класса, если он есть, должен явно вызвать его, чтобы правильно инициализировать часть экземпляра, относящуюся к базовому классу; например: super().__init__([args...]).

Поскольку __new__() и __init__() совместно участвуют в создании объектов (__new__() создаёт объект, а __init__() настраивает его), метод __init__() не может возвращать значение, отличное от None; в противном случае во время выполнения будет вызвано исключение TypeError.

object.__del__(self)

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

Метод __del__() может отложить уничтожение экземпляра, создав на него новую ссылку, хотя делать это не рекомендуется. Это называется воскрешением объекта. Зависит от реализации, будет ли __del__() вызван повторно, когда воскрешённый объект собираются уничтожить; текущая реализация CPython вызывает его только один раз.

Не гарантируется, что методы __del__() будут вызваны для объектов, существующих на момент завершения интерпретатора. weakref.finalize предоставляет простой способ зарегистрировать функцию очистки, которая будет вызвана при сборке объекта мусорщиком.

Примечание

del x не вызывает x.__del__() напрямую: первый уменьшает счётчик ссылок на x на единицу, а последний вызывается, только когда счётчик ссылок x достигает нуля.

Особенность реализации CPython: Цикл ссылок может помешать счётчику ссылок объекта достичь нуля. В этом случае цикл позднее обнаруживается и удаляется циклическим сборщиком мусора. Частой причиной циклов ссылок является перехват исключения в локальной переменной. Тогда локальные переменные кадра ссылаются на исключение, которое ссылается на собственную трассировку стека, а та, в свою очередь, ссылается на локальные переменные всех кадров, попавших в трассировку.

См. также

Документация модуля gc.

Предупреждение

Из-за нестабильных обстоятельств, при которых вызываются методы __del__(), возникающие во время их выполнения исключения игнорируются, а вместо этого предупреждение выводится в sys.stderr. В частности:

  • __del__() может быть вызван во время выполнения произвольного кода, в том числе в любом потоке. Если __del__() потребуется захватить блокировку или обратиться к другому блокирующему ресурсу, может возникнуть взаимная блокировка: этот ресурс уже может быть занят кодом, выполнение которого прервано ради вызова __del__().
  • __del__() может выполняться во время завершения интерпретатора. В результате глобальные переменные, к которым ему нужно обратиться (включая переменные других модулей), могут быть уже удалены или установлены в None. Python гарантирует, что глобальные переменные, имена которых начинаются с одного символа подчёркивания, удаляются из своего модуля до удаления остальных глобальных переменных; если на такие переменные нет других ссылок, это может помочь обеспечить доступность импортированных модулей к моменту вызова метода __del__().
object.__repr__(self)

Вызывается встроенной функцией repr() для вычисления «официального» строкового представления объекта. По возможности оно должно выглядеть как корректное выражение Python, которое можно использовать для воссоздания объекта с тем же значением (при наличии подходящего окружения). Если это невозможно, следует вернуть строку вида <...some useful description...>. Возвращаемое значение должно быть строковым объектом. Если класс определяет __repr__(), но не __str__(), то __repr__() также используется, когда требуется «неформальное» строковое представление экземпляров этого класса.

Обычно этот метод используется для отладки, поэтому важно, чтобы представление содержало много информации и было однозначным. Реализацию по умолчанию предоставляет сам класс object.

object.__str__(self)

Вызывается функцией str(object), реализацией __format__() по умолчанию и встроенной функцией print() для вычисления «неформального» или удобного для печати строкового представления объекта. Возвращаемое значение должно быть объектом str.

Этот метод отличается от object.__repr__() тем, что от __str__() не требуется возвращать корректное выражение Python: можно использовать более удобное или краткое представление.

Реализация по умолчанию, определённая встроенным типом object, вызывает object.__repr__().

object.__bytes__(self)

Вызывается функцией bytes для вычисления байтового строкового представления объекта. Метод должен возвращать объект bytes. Сам класс object этот метод не предоставляет.

object.__format__(self, format_spec)

Вызывается встроенной функцией format(), а также при вычислении форматированных строковых литералов и метода str.format(), чтобы получить «форматированное» строковое представление объекта. Аргумент format_spec — это строка с описанием желаемых параметров форматирования. Интерпретацию аргумента format_spec определяет тип, реализующий __format__(); однако большинство классов либо делегируют форматирование одному из встроенных типов, либо используют аналогичный синтаксис параметров форматирования.

Описание стандартного синтаксиса форматирования см. в разделе Мини-язык спецификаций формата.

Возвращаемое значение должно быть строковым объектом.

Реализации по умолчанию класса object следует передавать пустую строку format_spec. Она делегирует вызов __str__().

Изменено в версии 3.4: Метод __format__ самого object теперь вызывает TypeError, если ему передана непустая строка.

Изменено в версии 3.7: Теперь object.__format__(x, '') эквивалентно str(x), а не format(str(x), '').

object.__lt__(self, other)
object.__le__(self, other)
object.__eq__(self, other)
object.__ne__(self, other)
object.__gt__(self, other)
object.__ge__(self, other)

Это так называемые методы «расширенного сравнения». Соответствие символов операторов и имён методов таково: x<y вызывает x.__lt__(y), x<=y вызывает x.__le__(y), x==y вызывает x.__eq__(y), x!=y вызывает x.__ne__(y), x>y вызывает x.__gt__(y), а x>=y вызывает x.__ge__(y).

Метод расширенного сравнения может вернуть одиночный объект NotImplemented, если он не реализует операцию для данной пары аргументов. По соглашению, при успешном сравнении возвращаются False и True. Однако эти методы могут возвращать любое значение, поэтому, если оператор сравнения используется в булевом контексте (например, в условии инструкции if), Python вызывает для этого значения bool(), чтобы определить, является ли результат истинным или ложным.

По умолчанию object реализует __eq__() с помощью is, возвращая NotImplemented при ложном сравнении: True if x is y else NotImplemented. По умолчанию __ne__() делегирует вызов __eq__() и инвертирует результат, если он не равен NotImplemented. Других подразумеваемых связей между операторами сравнения или их реализациями по умолчанию нет; например, истинность (x<y or x==y) не подразумевает x<=y. Сведения об автоматическом создании операций упорядочения на основе одной основной операции см. в разделе functools.total_ordering().

По умолчанию класс object предоставляет реализации, согласованные с разделом Сравнение значений: равенство определяется идентичностью объектов, а сравнение порядка вызывает TypeError. Каждый метод по умолчанию может непосредственно выдать такой результат, но также может вернуть NotImplemented.

В абзаце о __hash__() приведены важные замечания о создании хешируемых объектов, поддерживающих пользовательские операции сравнения и пригодных для использования в качестве ключей словаря.

Версий этих методов с переставленными аргументами (которые использовались бы, если левый аргумент не поддерживает операцию, а правый поддерживает) нет; вместо этого __lt__() и __gt__() являются отражениями друг друга, __le__() и __ge__() также являются отражениями друг друга, а __eq__() и __ne__() являются отражениями самих себя. Если операнды имеют разные типы и тип правого операнда является прямым или косвенным подклассом типа левого операнда, отражённый метод правого операнда имеет приоритет; в противном случае приоритет имеет метод левого операнда. Виртуальные подклассы не учитываются.

Если ни один подходящий метод не возвращает значение, отличное от NotImplemented, операторы == и != переходят соответственно к is и is not.

object.__hash__(self)

Вызывается встроенной функцией hash() и при операциях с элементами хешируемых коллекций, включая set, frozenset и dict. Метод __hash__() должен возвращать целое число. Единственное обязательное свойство: объекты, которые сравниваются как равные, должны иметь одинаковое хеш-значение; рекомендуется объединять хеш-значения компонентов объекта, участвующих также в сравнении объектов, упаковывая их в кортеж и вычисляя хеш кортежа. Пример:

def __hash__(self):
    return hash((self.name, self.nick, self.color))

Примечание

hash() усекает значение, возвращённое пользовательским методом объекта __hash__(), до размера Py_ssize_t. Обычно это 8 байт в 64-разрядных сборках и 4 байта в 32-разрядных. Если метод __hash__() объекта должен взаимодействовать со сборками разной разрядности, обязательно проверьте разрядность во всех поддерживаемых сборках. Это можно легко сделать с помощью python -c "import sys; print(sys.hash_info.width)".

Если класс не определяет метод __eq__(), ему также не следует определять операцию __hash__(); если класс определяет __eq__(), но не __hash__(), его экземпляры нельзя будет использовать в качестве элементов хешируемых коллекций. Если класс определяет изменяемые объекты и реализует метод __eq__(), ему не следует реализовывать __hash__(), поскольку для работы хешируемых коллекций требуется неизменность хеш-значения ключа (если хеш-значение объекта изменится, он окажется не в той корзине хеш-таблицы).

Пользовательские классы по умолчанию имеют методы __eq__() и __hash__() (унаследованные от класса object); с ними все объекты сравниваются как неравные (кроме самих себя), а x.__hash__() возвращает подходящее значение, при котором x == y подразумевает одновременно x is y и hash(x) == hash(y).

У класса, переопределяющего __eq__() и не определяющего __hash__(), значение __hash__() неявно устанавливается в None. Если метод __hash__() класса равен None, при попытке получить хеш-значение экземпляра класса программа вызовет соответствующее исключение TypeError, а при проверке с помощью isinstance(obj, collections.abc.Hashable) экземпляр будет правильно распознан как нехешируемый.

Если классу, переопределяющему __eq__(), требуется сохранить реализацию __hash__() родительского класса, интерпретатору нужно явно сообщить об этом, установив __hash__ = <ParentClass>.__hash__.

Если класс, не переопределяющий __eq__(), хочет отключить поддержку хеширования, ему следует включить __hash__ = None в определение класса. Класс, определяющий собственный __hash__(), который явно вызывает исключение TypeError, будет ошибочно распознан как хешируемый при вызове isinstance(obj, collections.abc.Hashable).

Примечание

По умолчанию хеш-значения __hash__() объектов str и bytes «солью» дополняются непредсказуемым случайным значением. Хотя в рамках одного процесса Python они остаются неизменными, между повторными запусками Python их невозможно предсказать.

Это предназначено для защиты от отказа в обслуживании, вызванного специально подобранными входными данными, которые используют худшую производительность вставки в dict с вычислительной сложностью O(n2). Подробности см. на странице http://ocert.org/advisories/ocert-2011-003.html.

Изменение хеш-значений влияет на порядок итерации множеств. Python никогда не гарантировал этот порядок (и он обычно различается в 32-разрядных и 64-разрядных сборках).

См. также PYTHONHASHSEED.

Изменено в версии 3.3: Рандомизация хеширования включена по умолчанию.

object.__bool__(self)

Вызывается для реализации проверки истинности и встроенной операции bool(); должен возвращать False или True. Если этот метод не определён, вызывается __len__(), если он определён; объект считается истинным, если результат ненулевой. Если класс не определяет ни __len__(), ни __bool__() (как, например, сам класс object), все его экземпляры считаются истинными.

3.3.2. Настройка доступа к атрибутам

Для настройки смысла доступа к атрибутам (использования, присваивания или удаления x.name) экземпляров классов можно определить следующие методы.

object.__getattr__(self, name)

Вызывается, когда стандартный доступ к атрибуту завершается ошибкой AttributeError (либо __getattribute__() вызывает AttributeError, поскольку name не является атрибутом экземпляра или атрибутом в дереве классов для self; либо __get__() свойства name вызывает AttributeError). Этот метод должен вернуть вычисленное значение атрибута или вызвать исключение AttributeError. Сам класс object этот метод не предоставляет.

Обратите внимание: если атрибут найден обычным способом, __getattr__() не вызывается. (Это намеренная асимметрия между __getattr__() и __setattr__().) Это сделано как из соображений эффективности, так и потому, что иначе у __getattr__() не было бы способа получить доступ к другим атрибутам экземпляра. Обратите внимание: по крайней мере для переменных экземпляра можно имитировать полный контроль, не помещая значения в словарь атрибутов экземпляра (а сохраняя их в другом объекте). О способе получить полный контроль над доступом к атрибутам см. метод __getattribute__() ниже.

object.__getattribute__(self, name)

Безусловно вызывается для реализации доступа к атрибутам экземпляров класса. Если класс также определяет __getattr__(), последний не будет вызван, если только __getattribute__() не вызовет его явно или не вызовет исключение AttributeError. Этот метод должен вернуть вычисленное значение атрибута или вызвать исключение AttributeError. Чтобы избежать бесконечной рекурсии в этом методе, его реализация всегда должна вызывать метод базового класса с тем же именем для доступа к необходимым атрибутам, например, object.__getattribute__(self, name).

Примечание

Этот метод всё же может быть обойдён при поиске специальных методов вследствие неявного вызова синтаксисом языка или встроенными функциями. См. Поиск специальных методов.

При некоторых обращениях к атрибутам, чувствительных с точки зрения безопасности, вызывает событие аудита object.__getattr__ с аргументами obj и name.

object.__setattr__(self, name, value)

Вызывается при попытке присвоить значение атрибуту. Вызывается вместо стандартного механизма (то есть сохранения значения в словаре экземпляра). name — имя атрибута, value — присваиваемое ему значение.

Если __setattr__() нужно присвоить значение атрибуту экземпляра, следует вызвать метод базового класса с тем же именем, например, object.__setattr__(self, name, value).

При некоторых присваиваниях атрибутам, чувствительных с точки зрения безопасности, вызывает событие аудита object.__setattr__ с аргументами obj, name, value.

object.__delattr__(self, name)

Подобен __setattr__(), но вызывается при удалении атрибута, а не при присваивании. Его следует реализовывать только в том случае, если для объекта имеет смысл del obj.name.

При некоторых удалениях атрибутов, чувствительных с точки зрения безопасности, вызывает событие аудита object.__delattr__ с аргументами obj и name.

object.__dir__(self)

Вызывается, когда для объекта вызывается dir(). Должен возвращаться итерируемый объект. dir() преобразует возвращённый итерируемый объект в список и сортирует его.

3.3.2.1. Настройка доступа к атрибутам модуля

Специальные имена __getattr__ и __dir__ также можно использовать для настройки доступа к атрибутам модуля. Функция __getattr__ на уровне модуля должна принимать один аргумент — имя атрибута — и возвращать вычисленное значение или вызывать AttributeError. Если атрибут не найден в объекте модуля при обычном поиске, то есть с помощью object.__getattribute__(), перед вызовом AttributeError в __dict__ модуля выполняется поиск __getattr__. Если он найден, он вызывается с именем атрибута, а результат возвращается.

Функция __dir__ должна принимать аргументы и возвращать итерируемый объект строк, представляющих имена, доступные в модуле. Если эта функция определена, она заменяет стандартный поиск dir() в модуле.

Для более точной настройки поведения модуля (установки атрибутов, свойств и т. д.) можно присвоить атрибуту __class__ объекта модуля подкласс types.ModuleType. Например:

import sys
from types import ModuleType

class VerboseModule(ModuleType):
    def __repr__(self):
        return f'Verbose {self.__name__}'

    def __setattr__(self, attr, value):
        print(f'Setting {attr}...')
        super().__setattr__(attr, value)

sys.modules[__name__].__class__ = VerboseModule

Примечание

Определение __getattr__ модуля и установка __class__ модуля влияют только на поиск, выполняемый с помощью синтаксиса доступа к атрибутам. Прямой доступ к глобальным переменным модуля (из кода внутри модуля или через ссылку на словарь глобальных переменных модуля) они не затрагивают.

Изменено в версии 3.5: атрибут модуля __class__ теперь доступен для записи.

Добавлено в версии 3.7: атрибуты модуля __getattr__ и __dir__.

См. также

PEP 562 — Module __getattr__ и __dir__

Описывает функции __getattr__ и __dir__ для модулей.

3.3.2.2. Реализация дескрипторов

Следующие методы применяются только тогда, когда экземпляр класса, содержащего этот метод (так называемого класса дескриптора), находится в классе владельце (дескриптор должен находиться либо в словаре класса-владельца, либо в словаре класса одного из его родителей). В приведённых ниже примерах «атрибут» — это атрибут, имя которого является ключом свойства в __dict__ класса-владельца. Сам класс object не реализует ни один из этих протоколов.

object.__get__(self, instance, owner=None)

Вызывается для получения атрибута класса-владельца (доступ к атрибуту класса) или экземпляра этого класса (доступ к атрибуту экземпляра). Необязательный аргумент owner — класс-владелец, а instance — экземпляр, через который был получен доступ к атрибуту, или None, если доступ к атрибуту осуществляется через owner.

Этот метод должен вернуть вычисленное значение атрибута или вызвать исключение AttributeError.

PEP 252 определяет, что __get__() можно вызывать с одним или двумя аргументами. Встроенные дескрипторы Python поддерживают эту спецификацию, однако в некоторых сторонних инструментах могут использоваться дескрипторы, которым требуются оба аргумента. Собственная реализация Python метода __getattribute__() всегда передаёт оба аргумента, независимо от того, нужны ли они.

object.__set__(self, instance, value)

Вызывается для присваивания атрибуту экземпляра instance класса-владельца нового значения value.

Обратите внимание: добавление __set__() или __delete__() меняет тип дескриптора на «дескриптор данных». Подробнее см. Вызов дескрипторов.

object.__delete__(self, instance)

Вызывается для удаления атрибута экземпляра instance класса-владельца.

У экземпляров дескрипторов также может присутствовать атрибут __objclass__:

object.__objclass__

Модуль inspect интерпретирует атрибут __objclass__ как указание класса, в котором был определён этот объект (правильная установка этого атрибута может помочь при интроспекции динамических атрибутов класса во время выполнения). Для вызываемых объектов он может указывать, что в качестве первого позиционного аргумента ожидается или требуется экземпляр заданного типа (или его подкласса). Например, CPython устанавливает этот атрибут для несвязанных методов, реализованных на C.

3.3.2.3. Вызов дескрипторов

В общем случае дескриптор — это атрибут объекта с «поведением связывания», доступ к которому переопределён методами протокола дескрипторов: __get__(), __set__() и __delete__(). Если для объекта определён любой из этих методов, он считается дескриптором.

При стандартном доступе к атрибутам атрибут получают из словаря объекта, присваивают ему значение или удаляют его из этого словаря. Например, цепочка поиска для a.x начинается с a.__dict__['x'], затем включает type(a).__dict__['x'] и продолжается классами-родителями type(a), исключая метаклассы.

Однако если найденное значение — объект, определяющий один из методов дескриптора, Python может переопределить стандартное поведение и вызвать вместо него метод дескриптора. Положение этого вызова в цепочке приоритетов зависит от того, какие методы дескриптора определены и как они вызываются.

Отправной точкой для вызова дескриптора является связывание, a.x. Способ формирования аргументов зависит от a:

Прямой вызов

Самый простой и наименее распространённый вариант — непосредственный вызов метода дескриптора пользовательским кодом: x.__get__(a).

Связывание с экземпляром

При связывании с экземпляром объекта a.x преобразуется в вызов: type(a).__dict__['x'].__get__(a, type(a)).

Связывание с классом

При связывании с классом A.x преобразуется в вызов: A.__dict__['x'].__get__(None, A).

Связывание через super

Поиск с точкой, например super(A, a).x, выполняет поиск в a.__class__.__mro__ базового класса B, следующего за A, а затем возвращает B.__dict__['x'].__get__(a, A). Если это не дескриптор, x возвращается без изменений.

При связывании с экземплярами приоритет вызова дескриптора зависит от того, какие методы дескриптора определены. Дескриптор может определять любую комбинацию методов __get__(), __set__() и __delete__(). Если он не определяет __get__(), при обращении к атрибуту будет возвращён сам объект-дескриптор, если только в словаре экземпляра объекта нет соответствующего значения. Если дескриптор определяет __set__() и/или __delete__(), он является дескриптором данных; если не определяет ни один из них — дескриптором без данных. Обычно дескрипторы данных определяют оба метода — __get__() и __set__(), а дескрипторы без данных имеют только метод __get__(). Дескрипторы данных с определёнными методами __get__() и __set__() (и/или __delete__()) всегда имеют приоритет над переопределением в словаре экземпляра. В отличие от них, дескрипторы без данных могут быть переопределены экземплярами.

Методы Python (включая методы, декорированные с помощью @staticmethod и @classmethod) реализованы как дескрипторы без данных. Поэтому экземпляры могут переопределять методы. Это позволяет отдельным экземплярам приобретать поведение, отличающееся от поведения других экземпляров того же класса.

Функция property() реализована как дескриптор данных. Поэтому экземпляры не могут переопределять поведение свойства.

3.3.2.4. __slots__

__slots__ позволяет явно объявить элементы данных (например, свойства) и запретить создание __dict__ и __weakref__ (если они явно не объявлены в __slots__ и недоступны в родительском классе).

Экономия памяти по сравнению с использованием __dict__ может быть значительной. Скорость поиска атрибутов также может существенно повыситься.

object.__slots__

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

Примечания по использованию __slots__:

  • При наследовании от класса без __slots__ атрибуты __dict__ и __weakref__ экземпляров всегда будут доступны.
  • Без переменной __dict__ экземплярам нельзя присваивать новые переменные, не перечисленные в определении __slots__. Попытка присвоить значение неуказанному имени переменной вызывает AttributeError. Если требуется динамическое присваивание новых переменных, добавьте '__dict__' в последовательность строк в объявлении __slots__.
  • Если для каждого экземпляра не предусмотрена переменная __weakref__, классы, определяющие __slots__, не поддерживают создание weak references для своих экземпляров. Если нужна поддержка слабых ссылок, добавьте '__weakref__' в последовательность строк в объявлении __slots__.
  • __slots__ реализуется на уровне класса путём создания дескрипторов для каждого имени переменной. В результате атрибуты класса нельзя использовать для задания значений по умолчанию для переменных экземпляра, определённых в __slots__: в противном случае атрибут класса перезапишет назначение дескриптора.
  • Действие объявления __slots__ не ограничивается классом, в котором оно определено. Объявленные в родительских классах __slots__ доступны в дочерних классах. Однако экземпляры дочернего подкласса получат __dict__ и __weakref__, если подкласс также не определяет __slots__ (в котором должны быть указаны только имена дополнительных слотов).
  • Если класс определяет слот, уже определённый в базовом классе, переменная экземпляра, определённая слотом базового класса, становится недоступной (кроме случая, когда её дескриптор извлекается непосредственно из базового класса). Это делает смысл программы неопределённым. В будущем может быть добавлена проверка, предотвращающая такую ситуацию.
  • Если для класса, производного от "variable-length" built-in type, например int, bytes или tuple, определён непустой __slots__, будет вызвано исключение TypeError.
  • Для __slots__ можно использовать любой итерируемый объект, не являющийся строкой.
  • Если для задания __slots__ используется dictionary, ключи словаря используются как имена слотов. Значения словаря можно использовать для задания отдельных строк документации атрибутов; они распознаются функцией inspect.getdoc() и отображаются в выводе help().
  • Присваивание __class__ работает только в том случае, если у обоих классов одинаковые __slots__.
  • Множественное наследование от нескольких родительских классов со слотами допустимо, но только у одного родительского класса могут быть атрибуты, созданные слотами (у остальных базовых классов структура слотов должна быть пустой). Нарушение этого правила вызывает TypeError.
  • Если для __slots__ используется итератор, для каждого значения итератора создаётся дескриптор. Однако атрибут __slots__ будет пустым итератором.

3.3.3. Настройка создания классов

Всякий раз, когда класс наследуется от другого класса, для родительского класса вызывается __init_subclass__(). Благодаря этому можно создавать классы, изменяющие поведение подклассов. Это тесно связано с декораторами классов, однако декораторы классов влияют только на конкретный класс, к которому они применены, а __init_subclass__ применяется только к будущим подклассам класса, в котором определён метод.

classmethod object.__init_subclass__(cls)

Этот метод вызывается всякий раз, когда от содержащего его класса создаётся подкласс. В этом случае cls — новый подкласс. Если метод определён как обычный метод экземпляра, он неявно преобразуется в метод класса.

Ключевые аргументы, переданные новому классу, передаются методу __init_subclass__ родительского класса. Для совместимости с другими классами, использующими __init_subclass__, следует извлечь нужные ключевые аргументы и передать остальные базовому классу, как показано ниже:

class Philosopher:
    def __init_subclass__(cls, /, default_name, **kwargs):
        super().__init_subclass__(**kwargs)
        cls.default_name = default_name

class AustralianPhilosopher(Philosopher, default_name="Bruce"):
    pass

Реализация по умолчанию object.__init_subclass__ ничего не делает, но вызывает ошибку, если ей переданы какие-либо аргументы.

Примечание

Подсказка метакласса metaclass обрабатывается остальными механизмами системы типов и никогда не передаётся реализациям __init_subclass__. Фактический метакласс (а не явную подсказку) можно получить с помощью type(cls).

Добавлено в версии 3.6.

При создании класса type.__new__() просматривает переменные класса и вызывает соответствующие методы, имеющие хук __set_name__().

object.__set_name__(self, owner, name)

Автоматически вызывается при создании содержащего класса owner. Объекту присвоено имя name в этом классе:

class A:
    x = C()  # Automatically calls: x.__set_name__(A, 'x')

Если переменная класса присваивается после создания класса, __set_name__() не будет вызван автоматически. При необходимости __set_name__() можно вызвать напрямую:

class A:
   pass

c = C()
A.x = c                  # The hook is not called
c.__set_name__(A, 'x')   # Manually invoke the hook

Подробнее см. раздел Создание объекта класса.

Добавлено в версии 3.6.

3.3.3.1. Метаклассы

По умолчанию классы создаются с помощью type(). Тело класса выполняется в новом пространстве имён, а имя класса локально связывается с результатом type(name, bases, namespace).

Процесс создания класса можно настроить, передав ключевой аргумент metaclass в строке определения класса или унаследовавшись от существующего класса, содержащего такой аргумент. В следующем примере и MyClass, и MySubclass являются экземплярами Meta:

class Meta(type):
    pass

class MyClass(metaclass=Meta):
    pass

class MySubclass(MyClass):
    pass

Все остальные ключевые аргументы, указанные в определении класса, передаются всем операциям метакласса, описанным ниже.

При выполнении определения класса происходят следующие шаги:

  • разрешаются записи MRO;
  • определяется подходящий метакласс;
  • подготавливается пространство имён класса;
  • выполняется тело класса;
  • создаётся объект класса.

3.3.3.2. Разрешение записей MRO

object.__mro_entries__(self, bases)

Если базовый класс, указанный в определении класса, не является экземпляром type, для него ищется метод __mro_entries__(). Если такой метод __mro_entries__() найден, при создании класса базовый класс заменяется результатом вызова __mro_entries__(). Методу передаётся исходный кортеж базовых классов в параметре bases, и он должен вернуть кортеж классов, которые будут использоваться вместо базового класса. Возвращённый кортеж может быть пустым: в этом случае исходный базовый класс игнорируется.

См. также

types.resolve_bases()

Динамически разрешает базовые классы, которые не являются экземплярами type.

types.get_original_bases()

Получает «исходные базовые классы» до их изменения с помощью __mro_entries__().

PEP 560

Основная поддержка модуля typing и универсальных типов.

3.3.3.3. Определение подходящего метакласса

Подходящий метакласс для определения класса определяется следующим образом:

  • если не указаны ни базовые классы, ни явный метакласс, используется type();
  • если указан явный метакласс и он не является экземпляром type(), он непосредственно используется в качестве метакласса;
  • если в качестве явного метакласса указан экземпляр type() или определены базовые классы, используется наиболее производный метакласс.

Наиболее производный метакласс выбирается из явно заданного метакласса (если он есть) и метаклассов (то есть type(cls)) всех указанных базовых классов. Наиболее производный метакласс является подтипом всех этих метаклассов-кандидатов. Если ни один из метаклассов-кандидатов не соответствует этому критерию, определение класса завершается ошибкой TypeError.

3.3.3.4. Подготовка пространства имён класса

После определения подходящего метакласса подготавливается пространство имён класса. Если у метакласса есть атрибут __prepare__, он вызывается как namespace = metaclass.__prepare__(name, bases, **kwds) (дополнительные ключевые аргументы, если они есть, берутся из определения класса). Метод __prepare__ следует реализовать как classmethod. Пространство имён, возвращённое __prepare__, передаётся в __new__, однако при создании итогового объекта класса пространство имён копируется в новый dict.

Если у метакласса нет атрибута __prepare__, пространство имён класса инициализируется как пустое упорядоченное отображение.

См. также

PEP 3115 — Метаклассы в Python 3000

Добавлен хук пространства имён __prepare__

3.3.3.5. Выполнение тела класса

Тело класса выполняется (приблизительно) как exec(body, globals(), namespace). Главное отличие от обычного вызова exec() состоит в том, что лексическая область видимости позволяет телу класса (включая любые методы) обращаться к именам из текущей и внешних областей видимости, если определение класса находится внутри функции.

Однако, даже если определение класса находится внутри функции, методы, определённые внутри класса, по-прежнему не могут видеть имена, определённые в области видимости класса. Доступ к переменным класса следует получать через первый параметр методов экземпляра или класса либо через неявную ссылку __class__ с лексической областью видимости, описанную в следующем разделе.

3.3.3.6. Создание объекта класса

После заполнения пространства имён класса в результате выполнения тела класса объект класса создаётся вызовом metaclass(name, bases, namespace, **kwds) (дополнительные ключевые аргументы, передаваемые здесь, совпадают с аргументами, переданными в __prepare__).

На этот объект класса ссылается форма super() без аргументов. __class__ — это неявная ссылка на замыкание, созданная компилятором, если какие-либо методы в теле класса ссылаются на __class__ или super. Благодаря этому форма super() без аргументов может корректно определить создаваемый класс на основе лексической области видимости, а класс или экземпляр, использованный для текущего вызова, определяется по первому аргументу, переданному методу.

Деталь реализации CPython: В CPython 3.6 и более поздних версиях ячейка __class__ передаётся метаклассу как запись __classcell__ в пространстве имён класса. Если она присутствует, её необходимо передать вызову type.__new__, чтобы класс был правильно инициализирован. Если этого не сделать, в Python 3.8 возникнет RuntimeError.

При использовании метакласса по умолчанию type или любого метакласса, который в конечном итоге вызывает type.__new__, после создания объекта класса выполняются следующие дополнительные шаги настройки:

  1. Метод type.__new__ собирает все атрибуты пространства имён класса, в которых определён метод __set_name__();
  2. Эти методы __set_name__ вызываются с создаваемым классом и присвоенным именем соответствующего атрибута;
  3. Для непосредственного родителя нового класса в порядке разрешения методов вызывается хук __init_subclass__().

После создания объекта класса он передаётся декораторам класса, включённым в определение класса (если они есть), а полученный объект привязывается в локальном пространстве имён как определённый класс.

Когда новый класс создаётся с помощью type.__new__, объект, переданный в качестве параметра пространства имён, копируется в новое упорядоченное отображение, а исходный объект отбрасывается. Новая копия оборачивается в прокси только для чтения, который становится атрибутом __dict__ объекта класса.

См. также

PEP 3135 — Новый super

Описывает неявную ссылку на замыкание __class__

3.3.3.7. Применение метаклассов

Возможности применения метаклассов практически безграничны. Среди рассматривавшихся вариантов — перечисления, ведение журналов, проверка интерфейсов, автоматическое делегирование, автоматическое создание свойств, прокси, фреймворки, а также автоматическая блокировка и синхронизация ресурсов.

3.3.4. Настройка проверок экземпляров и подклассов

Следующие методы используются для переопределения поведения по умолчанию встроенных функций isinstance() и issubclass().

В частности, метакласс abc.ABCMeta реализует эти методы, чтобы разрешить добавление абстрактных базовых классов (ABC) в качестве «виртуальных базовых классов» для любого класса или типа (включая встроенные типы), в том числе для других ABC.

type.__instancecheck__(self, instance)

Возвращает истину, если instance следует считать (прямым или косвенным) экземпляром class. Если метод определён, он вызывается для реализации isinstance(instance, class).

type.__subclasscheck__(self, subclass)

Возвращает истину, если subclass следует считать (прямым или косвенным) подклассом class. Если метод определён, он вызывается для реализации issubclass(subclass, class).

Обратите внимание, что эти методы ищутся в типе (метаклассе) класса. Их нельзя определять как методы класса в самом классе. Это согласуется с поиском специальных методов, вызываемых для экземпляров; только в данном случае экземпляр сам является классом.

См. также

PEP 3119 — Введение абстрактных базовых классов

Содержит спецификацию настройки поведения isinstance() и issubclass() с помощью __instancecheck__() и __subclasscheck__(), а также обоснование этой функциональности в контексте добавления в язык абстрактных базовых классов (см. модуль abc).

3.3.5. Эмуляция универсальных типов

При использовании аннотаций типов часто бывает полезно параметризовать универсальный тип с помощью квадратных скобок Python. Например, аннотацию list[int] можно использовать для обозначения list, все элементы которой имеют тип int.

См. также

PEP 484 — Подсказки типов

Представляет фреймворк Python для аннотаций типов

Типы универсальных псевдонимов

Документация по объектам, представляющим параметризованные универсальные классы

Generics, user-defined generics and typing.Generic

Документация по реализации универсальных классов, которые можно параметризовать во время выполнения и которые распознаются средствами статической проверки типов.

Класс, как правило, можно параметризовать, только если в нём определён специальный метод класса __class_getitem__().

classmethod object.__class_getitem__(cls, key)

Возвращает объект, представляющий специализацию универсального класса аргументами типов, указанными в key.

Если __class_getitem__() определён в классе, он автоматически становится методом класса. Поэтому при его определении нет необходимости декорировать его с помощью @classmethod.

3.3.5.1. Назначение __class_getitem__

Назначение __class_getitem__() — обеспечить параметризацию универсальных классов стандартной библиотеки во время выполнения, чтобы упростить применение к этим классам подсказок типов.

Чтобы реализовать пользовательские универсальные классы, которые можно параметризовать во время выполнения и которые распознаются средствами статической проверки типов, следует унаследоваться либо от класса стандартной библиотеки, уже реализующего __class_getitem__(), либо от typing.Generic, имеющего собственную реализацию __class_getitem__().

Пользовательские реализации __class_getitem__() в классах, определённых вне стандартной библиотеки, могут быть не распознаны сторонними средствами проверки типов, такими как mypy. Не рекомендуется использовать __class_getitem__() в каких-либо классах для целей, отличных от подсказок типов.

3.3.5.2. Сравнение __class_getitem__ и __getitem__

Обычно при обращении к объекту с помощью квадратных скобок вызывается метод экземпляра __getitem__(), определённый в классе объекта. Однако если объект, к которому обращаются, сам является классом, вместо него может быть вызван метод класса __class_getitem__(). Если __class_getitem__() определён правильно, он должен возвращать объект GenericAlias.

Получив выражение obj[x], интерпретатор Python выполняет примерно следующие действия, чтобы решить, следует ли вызвать __getitem__() или __class_getitem__():

from inspect import isclass

def subscribe(obj, x):
    """Return the result of the expression 'obj[x]'"""

    class_of_obj = type(obj)

    # If the class of obj defines __getitem__,
    # call class_of_obj.__getitem__(obj, x)
    if hasattr(class_of_obj, '__getitem__'):
        return class_of_obj.__getitem__(obj, x)

    # Else, if obj is a class and defines __class_getitem__,
    # call obj.__class_getitem__(x)
    elif isclass(obj) and hasattr(obj, '__class_getitem__'):
        return obj.__class_getitem__(x)

    # Else, raise an exception
    else:
        raise TypeError(
            f"'{class_of_obj.__name__}' object is not subscriptable"
        )

В Python все классы сами являются экземплярами других классов. Класс класса называется его метаклассом, и у большинства классов метаклассом является класс type. В type не определён __getitem__(), поэтому выражения вроде list[int], dict[str, float] и tuple[str, bytes] приводят к вызову __class_getitem__():

>>> # list has class "type" as its metaclass, like most classes:
>>> type(list)
<class 'type'>
>>> type(dict) == type(list) == type(tuple) == type(str) == type(bytes)
True
>>> # "list[int]" calls "list.__class_getitem__(int)"
>>> list[int]
list[int]
>>> # list.__class_getitem__ returns a GenericAlias object:
>>> type(list[int])
<class 'types.GenericAlias'>

Однако если у класса есть пользовательский метакласс, определяющий __getitem__(), обращение к классу с помощью квадратных скобок может привести к другому поведению. Пример можно найти в модуле enum:

>>> from enum import Enum
>>> class Menu(Enum):
...     """A breakfast menu"""
...     SPAM = 'spam'
...     BACON = 'bacon'
...
>>> # Enum classes have a custom metaclass:
>>> type(Menu)
<class 'enum.EnumMeta'>
>>> # EnumMeta defines __getitem__,
>>> # so __class_getitem__ is not called,
>>> # and the result is not a GenericAlias object:
>>> Menu['SPAM']
<Menu.SPAM: 'spam'>
>>> type(Menu['SPAM'])
<enum 'Menu'>

См. также

PEP 560 — Основная поддержка модуля typing и универсальных типов

Представляет __class_getitem__() и описывает, в каких случаях при обращении с помощью квадратных скобок вызывается __class_getitem__() вместо __getitem__()

3.3.6. Эмуляция вызываемых объектов

object.__call__(self[, args...])

Вызывается, когда экземпляр «вызывается» как функция; если этот метод определён, x(arg1, arg2, ...) приблизительно соответствует type(x).__call__(x, arg1, ...). Сам класс object не предоставляет этот метод.

3.3.7. Эмуляция типов контейнеров

Для реализации объектов-контейнеров можно определить следующие методы. Ни один из них не предоставляется самим классом object. Контейнеры обычно являются последовательностями (например, lists или tuples) либо отображениями (например, словари), но могут представлять и другие контейнеры. Первый набор методов используется для эмуляции последовательности или отображения; различие состоит в том, что для последовательности допустимыми ключами должны быть целые числа k, для которых 0 <= k < N, где N — длина последовательности, или объекты slice, задающие диапазон элементов. Также рекомендуется, чтобы отображения предоставляли методы keys(), values(), items(), get(), clear(), setdefault(), pop(), popitem(), copy() и update(), работающие подобно соответствующим методам стандартных объектов Python dictionary. Модуль collections.abc предоставляет MutableMapping — абстрактный базовый класс, помогающий создать эти методы на основе набора методов __getitem__(), __setitem__(), __delitem__() и keys(). Изменяемые последовательности должны предоставлять методы append(), count(), index(), extend(), insert(), pop(), remove(), reverse() и sort(), как стандартные объекты Python list. Наконец, типы последовательностей должны реализовывать сложение (то есть конкатенацию) и умножение (то есть повторение), определяя описанные ниже методы __add__(), __radd__(), __iadd__(), __mul__(), __rmul__() и __imul__(); другие числовые операторы определять не следует. Рекомендуется, чтобы и отображения, и последовательности реализовывали метод __contains__(), обеспечивающий эффективное использование оператора in; для отображений in должен выполнять поиск по ключам отображения, а для последовательностей — по значениям. Также рекомендуется, чтобы и отображения, и последовательности реализовывали метод __iter__(), обеспечивающий эффективный перебор контейнера; для отображений __iter__() должен выполнять перебор ключей объекта, а для последовательностей — значений.

object.__len__(self)

Вызывается для реализации встроенной функции len(). Должен возвращать длину объекта — целое число >= 0. Кроме того, объект, не определяющий метод __bool__(), но чей метод __len__() возвращает ноль, считается ложным в логическом контексте.

Особенность реализации CPython: В CPython длина должна быть не больше sys.maxsize. Если длина больше sys.maxsize, некоторые возможности (например, len()) могут вызвать исключение OverflowError. Чтобы проверка логического значения не вызывала OverflowError, объект должен определить метод __bool__().

object.__length_hint__(self)

Вызывается для реализации operator.length_hint(). Должен возвращать предполагаемую длину объекта (которая может быть больше или меньше фактической длины). Длина должна быть целым числом >= 0. Возвращаемым значением также может быть NotImplemented; оно обрабатывается так же, как если бы метод __length_hint__ вообще не существовал. Этот метод предназначен исключительно для оптимизации и никогда не требуется для корректной работы.

Добавлено в версии 3.4.

Примечание

Срезы обрабатываются исключительно следующими тремя методами. Вызов вида

a[1:2] = b

преобразуется в

a[slice(1, 2, None)] = b

и так далее. Пропущенные элементы среза всегда заполняются значением None.

object.__getitem__(self, key)

Вызывается для реализации вычисления self[key]. Для типов последовательностей допустимыми ключами должны быть целые числа. При необходимости они также могут поддерживать объекты slice. Поддержка отрицательных индексов также необязательна. Если key имеет недопустимый тип, может быть вызвано исключение TypeError; если key находится вне множества индексов последовательности (с учётом специальной интерпретации отрицательных значений), следует вызвать исключение IndexError. Для типов отображений, если key отсутствует (то есть не содержится в контейнере), следует вызвать исключение KeyError.

Примечание

Циклы for предполагают, что для недопустимых индексов будет вызвано исключение IndexError, чтобы можно было правильно определить конец последовательности.

Примечание

При индексации класса вместо __getitem__() может быть вызван специальный метод класса __class_getitem__(). Дополнительные сведения см. в разделе __class_getitem__ и __getitem__.

object.__setitem__(self, key, value)

Вызывается для реализации присваивания self[key]. Применяется то же примечание, что и для __getitem__(). Этот метод следует реализовывать только для отображений, если объекты поддерживают изменение значений ключей или добавление новых ключей, и для последовательностей, если элементы можно заменять. Для недопустимых значений key следует вызывать те же исключения, что и в методе __getitem__().

object.__delitem__(self, key)

Вызывается для реализации удаления self[key]. Применяется то же примечание, что и для __getitem__(). Этот метод следует реализовывать только для отображений, если объекты поддерживают удаление ключей, и для последовательностей, если из последовательности можно удалять элементы. Для недопустимых значений key следует вызывать те же исключения, что и в методе __getitem__().

object.__missing__(self, key)

Вызывается методом dict.__getitem__() для реализации self[key] в подклассах dict, если ключ отсутствует в словаре.

object.__iter__(self)

Этот метод вызывается, когда для контейнера требуется итератор. Метод должен возвращать новый объект-итератор, который может перебирать все объекты в контейнере. Для отображений он должен перебирать ключи контейнера.

object.__reversed__(self)

Вызывается встроенной функцией reversed() (если метод определён) для реализации обратного перебора. Метод должен возвращать новый объект-итератор, который перебирает все объекты контейнера в обратном порядке.

Если метод __reversed__() не предоставлен, встроенная функция reversed() будет использовать протокол последовательности (__len__() и __getitem__()). Объектам, поддерживающим протокол последовательности, следует предоставлять __reversed__(), только если они могут реализовать его эффективнее, чем встроенная функция reversed().

Операторы проверки принадлежности (in и not in) обычно реализуются посредством перебора контейнера. Однако объекты-контейнеры могут предоставить следующий специальный метод для более эффективной реализации, которая также не требует, чтобы объект был итерируемым.

object.__contains__(self, item)

Вызывается для реализации операторов проверки принадлежности. Должен возвращать истину, если item содержится в self, и ложь в противном случае. Для объектов-отображений следует проверять ключи отображения, а не значения или пары ключ-значение.

Для объектов, не определяющих __contains__(), проверка принадлежности сначала пытается выполнить перебор через __iter__(), а затем использует старый протокол перебора последовательности через __getitem__(). См. этот раздел справочника по языку.

3.3.8. Эмуляция числовых типов

Для эмуляции числовых объектов можно определить следующие методы. Методы, соответствующие операциям, которые не поддерживаются реализуемым типом числа (например, побитовые операции для нецелых чисел), определять не следует.

object.__add__(self, other)
object.__sub__(self, other)
object.__mul__(self, other)
object.__matmul__(self, other)
object.__truediv__(self, other)
object.__floordiv__(self, other)
object.__mod__(self, other)
object.__divmod__(self, other)
object.__pow__(self, other[, modulo])
object.__lshift__(self, other)
object.__rshift__(self, other)
object.__and__(self, other)
object.__xor__(self, other)
object.__or__(self, other)

Эти методы вызываются для реализации бинарных арифметических операций (+, -, *, @, /, //, %, divmod(), pow(), **, <<, >>, &, ^, |). Например, для вычисления выражения x + y, где x — экземпляр класса с методом __add__(), вызывается type(x).__add__(x, y). Метод __divmod__() должен быть эквивалентен использованию __floordiv__() и __mod__(); он не должен быть связан с __truediv__(). Обратите внимание: если необходимо поддерживать трёхаргументную версию встроенной функции pow(), метод __pow__() следует определить так, чтобы он принимал необязательный третий аргумент.

Если какой-либо из этих методов не поддерживает операцию с переданными аргументами, он должен возвращать NotImplemented.

object.__radd__(self, other)
object.__rsub__(self, other)
object.__rmul__(self, other)
object.__rmatmul__(self, other)
object.__rtruediv__(self, other)
object.__rfloordiv__(self, other)
object.__rmod__(self, other)
object.__rdivmod__(self, other)
object.__rpow__(self, other[, modulo])
object.__rlshift__(self, other)
object.__rrshift__(self, other)
object.__rand__(self, other)
object.__rxor__(self, other)
object.__ror__(self, other)

Эти методы вызываются для реализации бинарных арифметических операций (+, -, *, @, /, //, %, divmod(), pow(), **, <<, >>, &, ^, |) с переставленными операндами. Эти функции вызываются только в том случае, если левый операнд не поддерживает соответствующую операцию [3], а типы операндов различаются. [4] Например, для вычисления выражения x - y, где y — экземпляр класса с методом __rsub__(), вызывается type(y).__rsub__(y, x), если type(x).__sub__(x, y) возвращает NotImplemented.

Обратите внимание: трёхаргументная версия pow() не будет пытаться вызвать __rpow__() (правила приведения типов стали бы слишком сложными).

Примечание

Если тип правого операнда является подклассом типа левого операнда и этот подкласс предоставляет другую реализацию отражённого метода для данной операции, такой метод будет вызван раньше неотражённого метода левого операнда. Это поведение позволяет подклассам переопределять операции предков.

object.__iadd__(self, other)
object.__isub__(self, other)
object.__imul__(self, other)
object.__imatmul__(self, other)
object.__itruediv__(self, other)
object.__ifloordiv__(self, other)
object.__imod__(self, other)
object.__ipow__(self, other[, modulo])
object.__ilshift__(self, other)
object.__irshift__(self, other)
object.__iand__(self, other)
object.__ixor__(self, other)
object.__ior__(self, other)

Эти методы вызываются для реализации расширенных арифметических присваиваний (+=, -=, *=, @=, /=, //=, %=, **=, <<=, >>=, &=, ^=, |=). Эти методы должны пытаться выполнить операцию на месте (изменяя self) и возвращать результат (которым может быть, но не обязательно является, self). Если конкретный метод не определён или возвращает NotImplemented, расширенное присваивание использует обычные методы. Например, если x — экземпляр класса с методом __iadd__(), выражение x += y эквивалентно x = x.__iadd__(y) . Если __iadd__() отсутствует или x.__iadd__(y) возвращает NotImplemented, рассматриваются x.__add__(y) и y.__radd__(x), как при вычислении x + y. В некоторых ситуациях расширенное присваивание может привести к неожиданным ошибкам (см. Почему a_tuple[i] += [‘item’] вызывает исключение, хотя сложение работает?), однако такое поведение является частью модели данных.

object.__neg__(self)
object.__pos__(self)
object.__abs__(self)
object.__invert__(self)

Вызывается для реализации унарных арифметических операций (-, +, abs() и ~).

object.__complex__(self)
object.__int__(self)
object.__float__(self)

Вызывается для реализации встроенных функций complex(), int() и float(). Должен возвращать значение соответствующего типа.

object.__index__(self)

Вызывается для реализации operator.index(), а также каждый раз, когда Python требуется преобразовать числовой объект в целочисленный объект без потери точности (например, при работе со срезами или во встроенных функциях bin(), hex() и oct()). Наличие этого метода указывает на то, что числовой объект относится к целочисленному типу. Метод должен возвращать целое число.

Если методы __int__(), __float__() и __complex__() не определены, соответствующие встроенные функции int(), float() и complex() используют __index__().

object.__round__(self[, ndigits])
object.__trunc__(self)
object.__floor__(self)
object.__ceil__(self)

Вызывается для реализации встроенной функции round() и функций модуля math: trunc(), floor() и ceil(). Если в __round__() не передан аргумент ndigits, все эти методы должны возвращать значение объекта, усечённое до Integral (обычно int).

Встроенная функция int() использует __trunc__(), если не определены ни __int__(), ни __index__().

Изменено в версии 3.11: Использование __trunc__() функцией int() объявлено устаревшим.

3.3.9. Менеджеры контекста оператора with

Менеджер контекста — это объект, определяющий контекст выполнения, который устанавливается при выполнении оператора with. Менеджер контекста управляет входом в нужный контекст выполнения и выходом из него при выполнении блока кода. Обычно менеджеры контекста вызываются с помощью оператора with (описанного в разделе Оператор with), но их методы также можно вызывать напрямую.

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

Дополнительные сведения о менеджерах контекста см. в разделе Типы менеджеров контекста. Сам класс object не предоставляет методы менеджера контекста.

object.__enter__(self)

Войти в контекст выполнения, связанный с этим объектом. Оператор with привяжет возвращаемое этим методом значение к целевым объектам, указанным в предложении as оператора, если таковые имеются.

object.__exit__(self, exc_type, exc_value, traceback)

Выйти из контекста выполнения, связанного с этим объектом. Параметры описывают исключение, из-за которого был выполнен выход из контекста. Если выход из контекста произошёл без исключения, все три аргумента будут равны None.

Если передано исключение и метод должен подавить его (то есть предотвратить его распространение), он должен вернуть истинное значение. В противном случае после выхода из этого метода исключение будет обработано обычным образом.

Обратите внимание: методы __exit__() не должны повторно вызывать переданное исключение; это обязанность вызывающего кода.

См. также

PEP 343 — оператор “with”

Спецификация, предыстория и примеры оператора with в Python.

3.3.10. Настройка позиционных аргументов при сопоставлении с шаблоном класса

При использовании имени класса в шаблоне позиционные аргументы в шаблоне по умолчанию не допускаются, то есть case MyClass(x, y) обычно недопустимо без специальной поддержки в MyClass. Чтобы использовать такой шаблон, класс должен определить атрибут __match_args__.

object.__match_args__

Этой переменной класса можно присвоить кортеж строк. Когда этот класс используется в шаблоне класса с позиционными аргументами, каждый позиционный аргумент будет преобразован в именованный аргумент, используя соответствующее значение из __match_args__ в качестве имени аргумента. Отсутствие этого атрибута равносильно присваиванию ему значения ().

Например, если MyClass.__match_args__ — это ("left", "center", "right"), значит, case MyClass(x, y) эквивалентно case MyClass(left=x, center=y). Обратите внимание: число аргументов в шаблоне должно быть меньше или равно числу элементов в __match_args__; если оно больше, попытка сопоставления с шаблоном вызовет исключение TypeError.

Добавлено в версии 3.10.

См. также

PEP 634 — структурное сопоставление с шаблоном

Спецификация оператора match в Python.

3.3.11. Эмуляция буферных типов

Протокол буфера предоставляет способ, с помощью которого объекты Python могут обеспечивать эффективный доступ к низкоуровневому массиву в памяти. Этот протокол реализован встроенными типами, такими как bytes и memoryview, а сторонние библиотеки могут определять дополнительные буферные типы.

Хотя буферные типы обычно реализуются на C, протокол также можно реализовать на Python.

object.__buffer__(self, flags)

Вызывается, когда у self запрашивается буфер (например, конструктором memoryview). Аргумент flags — это целое число, представляющее тип запрошенного буфера и, например, определяющее, будет ли возвращённый буфер доступен только для чтения или для записи. inspect.BufferFlags предоставляет удобный способ интерпретировать флаги. Метод должен вернуть объект memoryview.

object.__release_buffer__(self, buffer)

Вызывается, когда буфер больше не нужен. Аргумент buffer — это объект memoryview, ранее возвращённый методом __buffer__(). Метод должен освободить все ресурсы, связанные с буфером. Этот метод должен возвращать None. Буферные объекты, которым не требуется выполнять очистку, не обязаны реализовывать этот метод.

Добавлено в версии 3.12.

См. также

PEP 688 — доступ к протоколу буфера из Python

Вводит методы Python __buffer__ и __release_buffer__.

collections.abc.Buffer

Абстрактный базовый класс для буферных типов.

3.3.12. Поиск специальных методов

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

>>> class C:
...     pass
...
>>> c = C()
>>> c.__len__ = lambda: 5
>>> len(c)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object of type 'C' has no len()

Причина такого поведения связана с рядом специальных методов, таких как __hash__() и __repr__(), которые реализованы всеми объектами, включая объекты типов. Если бы при неявном поиске этих методов использовался обычный процесс поиска, они не работали бы при вызове для самого объекта типа:

>>> 1 .__hash__() == hash(1)
True
>>> int.__hash__() == hash(int)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: descriptor '__hash__' of 'int' object needs an argument

Неправильную попытку вызвать таким образом несвязанный метод класса иногда называют «путаницей с метаклассом». Её можно избежать, обходя экземпляр при поиске специальных методов:

>>> type(1).__hash__(1) == hash(1)
True
>>> type(int).__hash__(int) == hash(int)
True

Помимо обхода атрибутов экземпляра ради корректной работы, при неявном поиске специальных методов обычно также обходится метод __getattribute__() даже метакласса объекта:

>>> class Meta(type):
...     def __getattribute__(*args):
...         print("Metaclass getattribute invoked")
...         return type.__getattribute__(*args)
...
>>> class C(object, metaclass=Meta):
...     def __len__(self):
...         return 10
...     def __getattribute__(*args):
...         print("Class getattribute invoked")
...         return object.__getattribute__(*args)
...
>>> c = C()
>>> c.__len__()                 # Explicit lookup via instance
Class getattribute invoked
10
>>> type(c).__len__(c)          # Explicit lookup via type
Metaclass getattribute invoked
10
>>> len(c)                      # Implicit lookup
10

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

3.4. Сопрограммы

3.4.1. Объекты, поддерживающие await

Объект, поддерживающий await, обычно реализует метод __await__(). Объекты-сопрограммы, возвращаемые функциями async def, поддерживают await.

Примечание

Объекты итераторов-генераторов, возвращаемые генераторами, декорированными с помощью types.coroutine(), также поддерживают await, но не реализуют __await__().

object.__await__(self)

Должен возвращать итератор. Предназначен для реализации объектов, поддерживающих await. Например, asyncio.Future реализует этот метод для совместимости с выражением await. Сам класс object не поддерживает await и не предоставляет этот метод.

Примечание

Язык не накладывает никаких ограничений на тип или значение объектов, выдаваемых итератором, возвращённым методом __await__, поскольку это зависит от реализации фреймворка асинхронного выполнения (например, asyncio), который управляет объектом, поддерживающим await.

Добавлено в версии 3.5.

См. также

PEP 492, где приведены дополнительные сведения об объектах, поддерживающих await.

3.4.2. Объекты-сопрограммы

Объекты-сопрограммы — это объекты, поддерживающие await. Выполнением сопрограммы можно управлять, вызывая __await__() и перебирая результат. Когда выполнение сопрограммы завершается и она возвращает значение, итератор вызывает исключение StopIteration, а атрибут value исключения содержит возвращаемое значение. Если сопрограмма вызывает исключение, итератор передаёт его дальше. Сопрограммы не должны напрямую вызывать необработанные исключения StopIteration.

У сопрограмм также есть перечисленные ниже методы, аналогичные методам генераторов (см. Методы итератора-генератора). Однако, в отличие от генераторов, сопрограммы напрямую не поддерживают итерацию.

Изменено в версии 3.5.2: Повторный вызов await для одной и той же сопрограммы приводит к RuntimeError.

coroutine.send(value)

Запускает или возобновляет выполнение сопрограммы. Если value равно None, это равносильно продвижению итератора, возвращённого методом __await__(). Если value не равно None, этот метод делегирует вызов методу send() итератора, из-за которого выполнение сопрограммы было приостановлено. Результат (возвращаемое значение, StopIteration или другое исключение) совпадает с результатом перебора возвращаемого значения __await__(), описанного выше.

coroutine.throw(value)
coroutine.throw(type[, value[, traceback]])

Вызывает указанное исключение в сопрограмме. Если у итератора, из-за которого выполнение сопрограммы было приостановлено, есть метод throw(), этот метод делегирует ему вызов. В противном случае исключение вызывается в точке приостановки. Результат (возвращаемое значение, StopIteration или другое исключение) совпадает с результатом перебора возвращаемого значения __await__(), описанного выше. Если исключение не перехвачено в сопрограмме, оно передаётся вызывающему коду.

Изменено в версии 3.12: Вторая сигнатура (type[, value[, traceback]]) объявлена устаревшей и может быть удалена в будущей версии Python.

coroutine.close()

Заставляет сопрограмму выполнить очистку и завершиться. Если выполнение сопрограммы приостановлено, этот метод сначала делегирует вызов методу close() итератора, из-за которого выполнение было приостановлено, если такой метод есть. Затем он вызывает GeneratorExit в точке приостановки, заставляя сопрограмму немедленно выполнить очистку. Наконец, сопрограмма помечается как завершившая выполнение, даже если она ещё не была запущена.

Объекты-сопрограммы автоматически закрываются описанным выше способом перед уничтожением.

3.4.3. Асинхронные итераторы

Асинхронный итератор может вызывать асинхронный код в своём методе __anext__.

Асинхронные итераторы можно использовать в операторе async for.

Сам класс object не предоставляет эти методы.

object.__aiter__(self)

Должен возвращать объект асинхронного итератора.

object.__anext__(self)

Должен возвращать объект, поддерживающий await, результатом которого будет следующее значение итератора. По окончании итерации следует вызывать исключение StopAsyncIteration.

Пример асинхронного итерируемого объекта:

class Reader:
    async def readline(self):
        ...

    def __aiter__(self):
        return self

    async def __anext__(self):
        val = await self.readline()
        if val == b'':
            raise StopAsyncIteration
        return val

Добавлено в версии 3.5.

Изменено в версии 3.7: До Python 3.7 метод __aiter__() мог возвращать объект, поддерживающий await, результатом которого был асинхронный итератор.

Начиная с Python 3.7, метод __aiter__() должен возвращать объект асинхронного итератора. Возврат любого другого значения приводит к исключению TypeError.

3.4.4. Асинхронные менеджеры контекста

Асинхронный менеджер контекста — это менеджер контекста, способный приостанавливать выполнение в своих методах __aenter__ и __aexit__.

Асинхронные менеджеры контекста можно использовать в операторе async with.

Сам класс object не предоставляет эти методы.

object.__aenter__(self)

Семантически аналогичен методу __enter__(); единственное отличие состоит в том, что он должен возвращать объект, поддерживающий await.

object.__aexit__(self, exc_type, exc_value, traceback)

Семантически аналогичен методу __exit__(); единственное отличие состоит в том, что он должен возвращать объект, поддерживающий await.

Пример класса асинхронного менеджера контекста:

class AsyncContextManager:
    async def __aenter__(self):
        await log('entering context')

    async def __aexit__(self, exc_type, exc, tb):
        await log('exiting context')

Добавлено в версии 3.5.

Сноски

[1]

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

[2]

Методы __hash__(), __iter__(), __reversed__() и __contains__() обрабатываются особым образом; остальные по-прежнему вызывают исключение TypeError, но могут делать это, полагаясь на поведение, при котором None не является вызываемым объектом.

[3]

Здесь «не поддерживает» означает, что у класса нет такого метода или метод возвращает NotImplemented. Не присваивайте методу значение None, если хотите принудительно перейти к отражённому методу правого операнда: это приведёт к противоположному результату и явно заблокирует такой переход.

[4]

Для операндов одного типа предполагается, что если обычный, а не отражённый метод — например, __add__() — завершается неудачей, то операция в целом не поддерживается. Поэтому отражённый метод не вызывается.

© 2001–2024 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.12/reference/datamodel.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API