Spec-Zone.ru › Python 3.12

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

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

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

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

Деталь реализации CPython: Для CPython, id(x) — это адрес памяти, где хранится x.

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

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

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

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

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

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

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

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

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

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

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

3.2.1. None

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

3.2.2. NotImplemented

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

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

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

3.2.3. Ellipsis

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

3.2.4. numbers.Number

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

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

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

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

3.2.4.1. numbers.Integral

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

Примечание

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

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

Integers (int)

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

Booleans (bool)

Они представляют булевы значения Ложь и Истина. Два объекта, представляющие значения False и True — единственные булевы объекты. Булев тип является подтипом целочисленного типа, и булевы значения ведут себя как значения 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. Используемый в выражении, срез представляет собой последовательность того же типа. Примечание выше об отрицательных индексах также относится к отрицательным позициям среза.

Некоторые последовательности также поддерживают «расширенные срезы» с третьим параметром «шаг»: 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

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

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

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

Примечание

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

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

Списки

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

Массивы байтов

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

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

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

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

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

Множества

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

Замороженные множества

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

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, содержащую глобальные переменные функции — глобальное пространство имен модуля, в котором была определена функция.

function.__closure__

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

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

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

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

Атрибут

Значение

function.__doc__

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

function.__name__

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

function.__qualname__

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

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

function.__module__

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

function.__defaults__

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

function.__code__

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

function.__dict__

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

function.__annotations__

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

function.__kwdefaults__

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

function.__type_params__

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

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

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

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

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

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

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

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

method.__self__

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

method.__func__

Относится к исходному объекту функции.

method.__doc__

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

method.__name__

Имя метода (такое же, как у method.__func__.__name__)

method.__module__

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3.2.8.8. Классы

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

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

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

3.2.9. Модули

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

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

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

__name__

Имя модуля.

__doc__

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

__file__

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

__annotations__

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

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

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

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

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

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

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

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

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

__name__

Имя класса.

__module__

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

__dict__

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

__bases__

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

__doc__

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

__annotations__

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

__type_params__

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

codeobject.co_cellvars

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

codeobject.co_freevars

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

codeobject.co_code

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

codeobject.co_consts

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

codeobject.co_names

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

codeobject.co_filename

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

codeobject.co_firstlineno

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

codeobject.co_lnotab

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

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

codeobject.co_stacksize

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

codeobject.co_flags

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

Следующие биты флага определены для co_flags: бит 0x04 установлен, если функция использует синтаксис *arguments для принятия произвольного количества позиционных аргументов; бит 0x08 установлен, если функция использует синтаксис **keywords для принятия произвольных аргументов ключевых слов; бит 0x20 установлен, если функция является генератором. См. Code Objects Bit Flags для подробной информации о семантике каждого флага, который может присутствовать.

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

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

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

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

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

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

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

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

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

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

Примечание

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

codeobject.co_lines()

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

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

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

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

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

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

См. также

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

PEP, который представил метод co_lines().

codeobject.replace(**kwargs)

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

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

3.2.13.2. Объекты стека

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

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

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

frame.f_code

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

frame.f_locals

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

frame.f_globals

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

frame.f_builtins

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

frame.f_lasti

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

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

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

frame.f_trace_lines

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

frame.f_trace_opcodes

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

frame.f_lineno

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

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

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

frame.clear()

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

RuntimeError генерируется, если кадр в настоящее время выполняется.

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

3.2.13.3. Объекты отслеживания исключений

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

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

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

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

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

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

traceback.tb_frame

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

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

traceback.tb_lineno

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

traceback.tb_lasti

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

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

traceback.tb_next

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

Изменено в версии 3.7: Этот атрибут теперь изменяемый.

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

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

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

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

slice.indices(self, length)

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

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

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

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

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

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

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

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

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

3.3.1. Основные настройки

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

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

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

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

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

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

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

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

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

object.__del__(self)

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

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

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

Примечание

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

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

См. также

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

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

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

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

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

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

object.__str__(self)

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

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

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

object.__bytes__(self)

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

object.__format__(self, format_spec)

Вызывается встроенной функцией format() и, как следствие, при оценке форматированных строковых литералов и метода 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__() для важных замечаний о создании хэшируемых объектов, поддерживающих пользовательские операции сравнения и которые могут использоваться в качестве ключей словарей.

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

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

object.__hash__(self)

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

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

Примечание

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

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

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

Это предназначено для защиты от отказа в обслуживании, вызванного тщательно подобранными входными данными, которые используют худшую производительность вставки в словарь, сложность 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, потому что имя не является атрибутом экземпляра или атрибутом в дереве классов для self; либо __get__() свойства имя вызывает AttributeError). Этот метод должен вернуть значение (вычисленное) атрибута или вызвать исключение AttributeError.

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

object.__getattribute__(self, name)

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

Примечание

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

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

object.__setattr__(self, name, value)

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

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

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

object.__delattr__(self, name)

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

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

object.__dir__(self)

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

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

Специальные имена __getattr__ и __dir__ также могут использоваться для настройки доступа к атрибутам модуля. Функция __getattr__ на уровне модуля должна принимать в качестве аргумента имя атрибута и возвращать вычисленное значение или вызывать исключение AttributeError. Если атрибут не найден в объекте модуля через обычный поиск, т. е. object.__getattribute__(), то __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. Реализация дескрипторов

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

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

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

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

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

object.__set__(self, instance, value)

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

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

object.__delete__(self, instance)

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

Экземпляры дескрипторов также могут иметь атрибут __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

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

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

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

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

3.3.2.4. __slots__

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

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

object.__slots__

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

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

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

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

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

classmethod object.__init_subclass__(cls)

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

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

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

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

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

Примечание

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

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

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

object.__set_name__(self, owner, name)

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

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

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

class A:
   pass

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

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

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

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

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

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

class Meta(type):
    pass

class MyClass(metaclass=Meta):
    pass

class MySubclass(MyClass):
    pass

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

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

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

3.3.3.2. Обработка записей MRO

object.__mro_entries__(self, bases)

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

См. также

types.resolve_bases()

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

types.get_original_bases()

Получить «исходные базовые классы» класса до модификаций методом __mro_entries__().

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__, после создания объекта класса вызываются следующие дополнительные шаги настройки:

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

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

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

См. также

PEP 3135 - Новый super

Описание неявной __class__ ссылки на замыкание

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

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

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

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

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

class.__instancecheck__(self, instance)

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

class.__subclasscheck__(self, subclass)

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

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

См. также

PEP 3119 - Введение Абстрактных Базовых Классов

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

3.3.5. Эмуляция обобщенных типов

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

См. также

PEP 484 - Type Hints

Введение в механизм Python для аннотаций типов

Типы обобщенных псевдонимов

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

Generics, user-defined generics and typing.Generic

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

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

classmethod object.__class_getitem__(cls, key)

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

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

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

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

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

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

3.3.5.2. __class_getitem__ и __getitem__

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

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

from inspect import isclass

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

    class_of_obj = type(obj)

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

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

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

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

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

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

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

См. также

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

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

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

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

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

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

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

object.__len__(self)

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

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

object.__length_hint__(self)

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

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

Примечание

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

a[1:2] = b

переводится в

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

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

object.__getitem__(self, key)

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

Примечание

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

Примечание

При индексировании класса может вызываться специальный метод класса __class_getitem__() вместо __getitem__(). Дополнительные сведения см. в разделе __class_getitem__ versus __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)

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

object.__reversed__(self)

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

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

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

object.__contains__(self, item)

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

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

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

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

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

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

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

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

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

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

Примечание

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

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

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

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

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

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

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

object.__index__(self)

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

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

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

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

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

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

3.3.9. Управляющие контекстом операторы с ключевым словом with

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

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

Для получения дополнительной информации об управляющих контекстах см. Типы управляющих контекстов.

object.__enter__(self)

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

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

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

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

Обратите внимание, что методы __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. Эмуляция типов буферов

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

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

object.__buffer__(self, flags)

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

object.__release_buffer__(self, buffer)

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

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

См. также

PEP 688 - Делает протокол буферов доступным в Python

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

collections.abc.Buffer

ABC для типов буферов.

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

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

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

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

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

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

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

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

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

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

3.4. Корутины

3.4.1. Объекты-ожидания

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

Примечание

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

object.__await__(self)

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

Примечание

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

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

См. также

PEP 492 для дополнительной информации об объектах-ожиданиях.

3.4.2. Объекты корутин

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

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

Изменено в версии 3.5.2: Вызов корутины более одного раза является RuntimeError.

coroutine.send(value)

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

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

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

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

coroutine.close()

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

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

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

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

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

object.__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__() мог возвращать объект-ожидание, который бы разрешался в асинхронный итератор.

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

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

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

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

object.__aenter__(self)

Семантически похож на __enter__(), единственное отличие состоит в том, что он должен возвращать awaitable.

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

Семантически похож на __exit__(), единственное отличие состоит в том, что он должен возвращать awaitable.

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

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

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

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

Примечания

[1]

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

[2]

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

[3]

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

[4]

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

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

Spec-Zone.ru

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