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

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

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

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

Детали реализации CPython: Для CPython id(x) - это адрес памяти, в которой хранится x.

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

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

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

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

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

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

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

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

3.2. Иерархия стандартных типов

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

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

3.2.1. Никто

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

3.2.2. Не реализовано

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

Смотрите Выполнение арифметических операций для получения более подробной информации.

Изменено в версии 3.9: Вычисление NotImplemented в логическом контексте не рекомендуется. Хотя в настоящее время оно оценивается как true, оно будет выдавать значение DeprecationWarning. В будущей версии Python оно вызовет значение TypeError.

3.2.3. Эллипс

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

3.2.4. numbers.Number

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

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

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

  • По возможности, представление осуществляется в базе данных 10.

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

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

  • Знак отображается только в том случае, если число отрицательное.

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

3.2.4.1. numbers.Integral

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

Примечание

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

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

Целые числа (int)

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

Логические значения (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, 1, …, n-1. Элемент i последовательности a выбирается с помощью a[i]. Некоторые последовательности, включая встроенные последовательности, интерпретируют отрицательные индексы, добавляя длину последовательности. Например, a[-2] равно a[n-2], предпоследний элемент последовательности a имеет длину n.

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

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

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

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

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

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

Струнные

Строка - это последовательность значений, представляющих кодовые точки в Юникоде. Все кодовые точки в диапазоне 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 можно использовать литералы Bytes (например, b'abc') и встроенный конструктор bytes(). Кроме того, объекты bytes могут быть преобразованы в строки с помощью метода decode().

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

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

Примечание

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

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

Списки

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

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

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

3.2.6. Установленные типы

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

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

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

Наборы

Они представляют собой изменяемый набор. Они создаются встроенным конструктором set() и впоследствии могут быть изменены несколькими способами, такими как add().

Замороженные наборы

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

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

Они представляют собой конечные наборы объектов, проиндексированных произвольными наборами индексов. Обозначение с нижним индексом a[k] выбирает элемент, индексированный с помощью k, из сопоставления a; это может использоваться в выражениях и в качестве цели присваиваний или инструкций 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, которая содержит global variables функции - глобальное пространство имен модуля, в котором была определена функция.

function.__closure__

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

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

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

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

Атрибут

Значение

function.__doc__

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

function.__name__

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

function.__qualname__

Значение функции qualified name. Смотрите также: __qualname__ attributes.

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

function.__module__

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

function.__defaults__

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

function.__code__

Символ code object, представляющий тело скомпилированной функции.

function.__dict__

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

function.__annotations__

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

function.__kwdefaults__

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

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

Детали реализации CPython: Текущая реализация CPython поддерживает только атрибуты функций для пользовательских функций. Атрибуты функций для built-in functions могут быть поддержаны в будущем.

Дополнительную информацию об определении функции можно получить из ее code object (доступного через атрибут __code__).

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

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

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

method.__self__

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

method.__func__

Ссылается на оригинал function object

method.__doc__

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

method.__name__

Название метода (такое же, как method.__func__.__name__)

method.__module__

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

Методы также поддерживают доступ (но не установку) к атрибутам произвольной функции в базовом function object.

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

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

Когда объект метода экземпляра создается путем извлечения объекта 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 является базовой функцией.

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

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

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

3.2.8.4. Функции сопрограммы

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

3.2.8.5. Функции асинхронного генератора

Функция или метод, который определяется с помощью async def и который использует оператор yield, называется asynchronous generator function. Такая функция при вызове возвращает объект asynchronous iterator, который может быть использован в инструкции async for для выполнения тела функции.

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

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

Объект встроенной функции - это оболочка для функции языка Си. Примерами встроенных функций являются 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 system, которая вызывается либо с помощью инструкции import, либо с помощью вызова таких функций, как importlib.import_module() и встроенных __import__(). Объект module имеет пространство имен, реализуемое объектом dictionary (это словарь, на который ссылается атрибут __globals__ функций, определенных в модуле). Ссылки на атрибуты преобразуются в поисковые запросы в этом словаре, например, m.x эквивалентно m.__dict__["x"]. Объект module не содержит объект code, используемый для инициализации модуля (поскольку он не нужен после завершения инициализации).

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

Предопределенные (доступные для записи) атрибуты:

__name__

Название модуля.

__doc__

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

__file__

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

__annotations__

Словарь, содержащий variable annotations, собранный во время выполнения основного текста модуля. Для получения рекомендаций по работе с __annotations__, пожалуйста, ознакомьтесь с Аннотации к лучшим практикам.

Специальный атрибут, доступный только для чтения: __dict__ - это пространство имен модуля как объекта словаря.

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

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

Пользовательские типы классов обычно создаются с помощью определений классов (см. раздел Определения классов). Класс имеет пространство имен, реализуемое объектом словаря. Ссылки на атрибуты класса преобразуются в поисковые запросы в этом словаре, например, C.x преобразуется в C.__dict__["x"] (хотя существует ряд перехватчиков, которые позволяют использовать другие способы поиска атрибутов). Если имя атрибута там не найдено, поиск атрибута продолжается в базовых классах. Этот поиск по базовым классам использует метод C3 resolution order, который корректно работает даже при наличии структур наследования типа «ромб», где существует несколько путей наследования, ведущих к общему предку. Дополнительные сведения о C3 MRO, используемом Python, можно найти в документации, сопровождающей выпуск 2.3, по адресу https://www.python.org/download/releases/2.3/mro/.

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

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

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

Особые атрибуты:

__name__

Название класса.

__module__

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

__dict__

Словарь, содержащий пространство имен класса.

__bases__

Кортеж, содержащий базовые классы в порядке их появления в списке базовых классов.

__doc__

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

__annotations__

Словарь, содержащий variable annotations, собранный во время выполнения основного текста класса. Для получения рекомендаций по работе с __annotations__, пожалуйста, ознакомьтесь с Аннотации к лучшим практикам.

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

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

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

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

Специальные атрибуты: __dict__ - это словарь атрибутов; __class__ - это класс экземпляра.

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

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

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

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

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

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

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

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

Имя функции

codeobject.co_qualname

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

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

codeobject.co_argcount

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

codeobject.co_posonlyargcount

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

codeobject.co_kwonlyargcount

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

codeobject.co_nlocals

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

codeobject.co_varnames

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

codeobject.co_cellvars

A tuple, содержащий имена local variables, на которые ссылаются вложенные функции внутри функции

codeobject.co_freevars

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

codeobject.co_code

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

codeobject.co_consts

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

codeobject.co_names

A tuple, содержащий имена, используемые bytecode в функции

codeobject.co_filename

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

codeobject.co_firstlineno

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

codeobject.co_lnotab

Строка, кодирующая отображение из bytecode, преобразуется в номера строк. Более подробную информацию смотрите в исходном коде интерпретатора.

codeobject.co_stacksize

Требуемый размер стека объекта code

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()

Возвращает итерацию по позициям исходного кода каждой инструкции bytecode в объекте code.

Итератор возвращает tuples, содержащий (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()

Возвращает итератор, который выдает информацию о последовательных диапазонах bytecodeс. Каждый полученный элемент представляет собой (start, end, lineno) tuple:

  • start (int) представляет собой смещение (включительно) от начала диапазона bytecode

  • end (int) представляет собой смещение (исключительное) конца диапазона bytecode

  • lineno - это int, представляющий номер строки диапазона bytecode, или None, если байт-коды в данном диапазоне не имеют номера строки

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

  • Первый полученный диапазон будет иметь значение start, равное 0.

  • Диапазоны (start, end) будут неубывающими и последовательными. То есть для любой пары tuples значение start второго будет равно значению end первого.

  • Ни один диапазон не будет изменен в обратном направлении: end >= start для всех троек.

  • Последний полученный tuple будет иметь размер end, равный размеру bytecode.

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

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

См.также

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

ОПТОСОЗ, который ввел метод co_lines().

codeobject.replace(**kwargs)

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

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

3.2.13.2. Обрамляющие объекты

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

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

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

frame.f_code

В этом кадре выполняется code object. При обращении к этому атрибуту возникает auditing event object.__getattr__ с аргументами obj и "f_code".

frame.f_locals

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

frame.f_globals

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

frame.f_builtins

Словарь, используемый фреймом для поиска built-in (intrinsic) names

frame.f_lasti

«Точная инструкция» объекта frame (это индекс в bytecode строке code object)

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), записав ее в этот атрибут.

3.2.13.2.3. Методы создания фреймового объекта

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

frame.clear()

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

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

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

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

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

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

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

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

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

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

traceback.tb_frame

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

При обращении к этому атрибуту возникает auditing event object.__getattr__ с аргументами obj и "tb_frame".

traceback.tb_lineno

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

traceback.tb_lasti

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

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

traceback.tb_next

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

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

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

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

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

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

slice.indices(self, length)

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

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

Статические объекты method предоставляют способ избежать преобразования объектов function в объекты method, описанный выше. Статический объект method - это оболочка для любого другого объекта, обычно определяемого пользователем объекта method. Когда объект статического метода извлекается из класса или экземпляра класса, фактически возвращаемый объект является обернутым объектом, который не подлежит дальнейшему преобразованию. Объекты статического метода также доступны для вызова. Объекты статического метода создаются встроенным конструктором staticmethod().

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

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

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

Класс может реализовывать определенные операции, которые вызываются с помощью специального синтаксиса (например, арифметические операции или индексирование и нарезка), определяя методы со специальными именами. Это подход Python к operator overloading, позволяющий классам определять свое собственное поведение по отношению к языковым операторам. Например, если класс определяет метод с именем __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).

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

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

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

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

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

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

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

object.__del__(self)

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

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

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

Примечание

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

Детали реализации CPython: Цикл ссылок может предотвратить обнуление значения счетчика ссылок для объекта. В этом случае цикл будет позже обнаружен и удален с помощью cyclic garbage collector. Частой причиной циклов ссылок является перехват исключения в локальной переменной. Локальные значения фрейма затем ссылаются на исключение, которое ссылается на свою собственную обратную трассировку, которая ссылается на локальные значения всех фреймов, перехваченных в ходе обратной трассировки.

См.также

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

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

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

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

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

object.__repr__(self)

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

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

object.__str__(self)

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

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

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

object.__bytes__(self)

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

object.__format__(self, format_spec)

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

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

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

Изменено в версии 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().

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

У этих методов нет версий с измененными аргументами (которые будут использоваться, когда левый аргумент не поддерживает операцию, а правый аргумент поддерживает); скорее, __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__(), до размера a Py_ssize_t. Обычно это 8 байт в 64-разрядных сборках и 4 байта в 32-разрядных сборках. Если объект __hash__() должен взаимодействовать с сборками разного размера, обязательно проверьте ширину во всех поддерживаемых сборках. Самый простой способ сделать это - с помощью python -c "import sys; print(sys.hash_info.width)".

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

Определяемые пользователем классы по умолчанию имеют методы __eq__() и __hash__(); с их помощью все объекты сравниваются неравномерно (кроме самих себя), а 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__(), все его экземпляры считаются истинными.

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

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

object.__getattr__(self, name)

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

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

object.__getattribute__(self, name)

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

Примечание

Этот метод все еще может быть пропущен при поиске специальных методов в результате неявного вызова с помощью синтаксиса языка или built-in functions. Смотрите Поиск по специальному методу.

Создает auditing event object.__getattr__ с аргументами obj, name.

object.__setattr__(self, name, value)

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

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

Создает auditing event object.__setattr__ с аргументами obj, name, value.

object.__delattr__(self, name)

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

Создает auditing event object.__delattr__ с аргументами obj, name.

object.__dir__(self)

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

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

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

Функция __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 - Модуль __getattr__ и __dir__

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

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

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

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

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

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

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

object.__set__(self, instance, value)

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

Обратите внимание, что добавление __set__() или __delete__() изменяет тип дескриптора на «дескриптор данных». Более подробную информацию смотрите в разделе Вызов дескрипторов.

object.__delete__(self, instance)

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

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

object.__objclass__

Атрибут __objclass__ интерпретируется модулем inspect как указывающий класс, в котором был определен этот объект (соответствующая настройка этого параметра может помочь в самоанализе динамических атрибутов класса во время выполнения). Для вызываемых объектов это может указывать на то, что экземпляр данного типа (или подкласса) ожидается или требуется в качестве первого позиционного аргумента (например, 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(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__ позволяют нам явно объявлять элементы данных (например, свойства) и запрещать создание __dict__ и __weakref__ (если они явно не объявлены в __slots__ или не доступны в родительском элементе).

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

object.__slots__

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

Указания по использованию __слотов__:

  • При наследовании от класса без __slots__ атрибуты экземпляров __dict__ и __weakref__ всегда будут доступны.

  • Без переменной __dict__ экземплярам нельзя присваивать новые переменные, не указанные в определении __slots__. При попытке присвоить имя переменной, не включенной в список, возникает AttributeError. Если требуется динамическое присвоение новых переменных, то добавьте '__dict__' к последовательности строк в объявлении __slots__.

  • Без переменной __weakref__ для каждого экземпляра классы, определяющие __slots__, не поддерживают weak references для своих экземпляров. Если требуется слабая поддержка ссылок, то добавьте '__weakref__' к последовательности строк в объявлении __slots__.

  • __слоты__ реализуются на уровне класса путем создания descriptors для каждого имени переменной. В результате атрибуты class нельзя использовать для установки значений по умолчанию для переменных экземпляра, определенных с помощью __slots__; в противном случае атрибут class заменил бы назначение дескриптора.

  • Действие объявления __slots__ не ограничивается классом, в котором оно определено. __slots__, объявленные в родительских классах, доступны в дочерних классах. Однако дочерние подклассы получат __dict__ и __weakref__, если они также не определяют __slots__ (которые должны содержать только имена любых дополнительных слотов).

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

  • TypeError будет поднят, если для класса, производного от a "variable-length" built-in type, определены непустые __слоты__, такие как int, bytes, и tuple.

  • Любое значение, отличное от строки iterable, может быть присвоено __slots__.

  • Если для назначения __слотов__ используется dictionary, то в качестве названий слотов будут использоваться ключи словаря. Значения словаря могут быть использованы для предоставления строк документации для каждого атрибута, которые будут распознаваться inspect.getdoc() и отображаться в выходных данных help().

  • __class__ присвоение работает только в том случае, если оба класса имеют одинаковые __слоты__.

  • Multiple inheritance с несколькими родительскими классами с прорезями можно использовать, но только одному родительскому классу разрешено иметь атрибуты, созданные слотами (другие базы должны иметь пустые макеты слотов) - нарушения приводят к появлению TypeError.

  • Если для __slots__ используется iterator, то для каждого значения итератора создается descriptor. Однако атрибут __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. Объекту присвоено имя в этом классе:

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

Если переменная class назначена после создания класса, __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

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

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

  • Записи ТОИР разрешены;

  • определен соответствующий метакласс;

  • пространство имен класса подготовлено;

  • тело класса выполняется;

  • объект класса создан.

3.3.3.2. Разрешение ввода данных ТОИР

object.__mro_entries__(self, bases)

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

См.также

types.resolve_bases()

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

PEP 560

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

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__, чтобы класс был инициализирован правильно. Невыполнение этого требования приведет к появлению RuntimeError в Python 3.8.

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

  1. Метод type.__new__ собирает все атрибуты в пространстве имен класса, которые определяют метод __set_name__();

  2. Эти методы __set_name__ вызываются с определением класса и присвоением имени этому конкретному атрибуту;

  3. Перехватчик __init_subclass__() вызывается для непосредственного родительского класса нового класса в порядке разрешения его метода.

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

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

См.также

PEP 3135 - Новый супер

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

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

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

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

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

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

class.__instancecheck__(self, instance)

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

class.__subclasscheck__(self, subclass)

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

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

См.также

PEP 3119 - Представляем абстрактные базовые классы

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

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

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

См.также

PEP 484 - Введите подсказки

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

Generic Alias Types

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

Дженерики, user-defined generics и typing.Generic

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

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

classmethod object.__class_getitem__(cls, key)

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

Когда он определен в классе, __class_getitem__() автоматически становится методом класса. Таким образом, нет необходимости оформлять его как @classmethod, когда он определен.

3.3.5.1. Цель создания __class_getitem__

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

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

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

3.3.5.2. __класс_getitem__ против __getitem__

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

Представлен с помощью expression 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 все классы сами по себе являются экземплярами других классов. Класс класса известен как metaclass этого класса, и большинство классов имеют класс 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 - Основная поддержка модуля ввода текста и универсальных типов

Вводим __class_getitem__() и описываем, когда subscription приводит к вызову __class_getitem__() вместо __getitem__()

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

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

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

3.3.7. Имитация типов контейнеров

Для реализации объектов-контейнеров могут быть определены следующие методы. Контейнерами обычно являются sequences (например, lists или tuples) или mappings (например, dictionaries), но могут представлять и другие контейнеры. Первый набор методов используется либо для эмуляции последовательности, либо для эмуляции отображения; разница в том, что для последовательности допустимыми ключами должны быть целые числа k, для которых 0 <= k < N, где N - длина последовательности, или slice объекты, которые определяют диапазон элементов. Также рекомендуется, чтобы сопоставления предоставляли методы keys(), values(), items(), get(), clear(), setdefault(), pop(), popitem(), copy(), и update(), которые ведут себя аналогично методам для стандартных объектов Python dictionary. Модуль collections.abc предоставляет MutableMapping abstract base class, который помогает создавать эти методы из базового набора __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]. Для типов sequence допустимыми ключами должны быть целые числа. Необязательно, они также могут поддерживать объекты slice. Поддержка отрицательного индекса также необязательна. Если key имеет неподходящий тип, может быть поднято значение TypeError; если key является значением вне набора индексов для последовательности (после какой-либо специальной интерпретации отрицательных значений), должно быть поднято значение IndexError. Для типов mapping, если ключ отсутствует (не в контейнере), должен быть поднят KeyError.

Примечание

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

Примечание

Когда subscripting a class, вместо __getitem__() может быть вызван специальный метод класса __class_getitem__(). Более подробную информацию смотрите в __класс_getitem__ против __getitem__.

object.__setitem__(self, key, value)

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

object.__delitem__(self, key)

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

object.__missing__(self, key)

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

object.__iter__(self)

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

object.__reversed__(self)

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

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

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

object.__contains__(self, item)

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

Для объектов, которые не определяют __contains__(), тест на принадлежность сначала выполняет итерацию с помощью __iter__(), затем по старому протоколу итерации последовательности с помощью __getitem__(), см. this section in the language reference.

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(). Если значение ndigits не передано в __round__(), все эти методы должны возвращать значение объекта, усеченное до Integral (обычно int).

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

Изменено в версии 3.11: Делегирование int() в __trunc__() не рекомендуется.

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

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

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

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

object.__enter__(self)

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

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

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

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

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

См.также

PEP 343 - Оператор «with»

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

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 - Сопоставление структурных паттернов

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

3.3.11. Поиск по специальному методу

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

>>> 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. Доступные объекты

Объект awaitable обычно реализует метод __await__(). Доступны функции Coroutine objects, возвращаемые из async def.

Примечание

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

object.__await__(self)

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

Примечание

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

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

См.также

PEP 492 для получения дополнительной информации о доступных объектах.

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

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

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

Изменено в версии 3.5.2: Это RuntimeError для ожидания в сопрограмме более одного раза.

coroutine.send(value)

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

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

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

coroutine.close()

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

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

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

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

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

object.__aiter__(self)

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

object.__anext__(self)

Должен возвращать значение ожидаемое, приводящее к следующему значению итератора. По окончании итерации должна возникнуть ошибка 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__() мог возвращать значение ожидаемое, которое преобразовалось бы в asynchronous iterator.

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

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

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

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

object.__aenter__(self)

Семантически аналогично __enter__(), с той лишь разницей, что он должен возвращать ожидаемый.

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

Семантически аналогично __exit__(), с той лишь разницей, что он должен возвращать ожидаемый.

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

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

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

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

Сноски

Вернуться на верх