Spec-Zone.ru › Python 3.11

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

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 могут или не могут ссылаться на один и тот же объект со значением один, в зависимости от реализации, но после c = []; d = [], c и d гарантированно ссылаются на два разных, уникальных, вновь созданных пустых списка. (Обратите внимание, что c = d = [] присваивает один и тот же объект как c, так и d.)

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. Его истинностное значение — истина.

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[i:j] выбирает все элементы с индексом k, такие что i <= k < j. Когда используется в качестве выражения, срез — это последовательность того же типа. Это подразумевает, что множество индексов переиндексировано так, что оно начинается с 0.

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

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

Подробность реализации (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, можно найти в документации, сопровождающей выпуск 2.3, по адресу https://www.python.org/download/releases/2.3/mro/.

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

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

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

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

__name__

Имя класса.

__module__

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

__dict__

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

__bases__

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

__doc__

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

__annotations__

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

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

Полностью квалифицированное имя функции

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 на номера строк. Подробнее см. исходный код интерпретатора.

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, если у байткодов в данном диапазоне нет номера строки

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

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

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

Новое в версии 3.10.

См. также

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

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

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__() его настраивает), никакое не-None значение не может быть возвращено методом __init__(); это приведет к ошибке TypeError во время выполнения.

object.__del__(self)

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

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

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

Примечание

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

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

См. также

Документацию модуля 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.

END_OF_DOCUMENT_MARKER
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__() являются собственными отражениями. Если операнды имеют разные типы, а тип правого операнда является прямым или косвенным подклассом типа левого операнда, метод правого операнда имеет приоритет, в противном случае приоритет метода левого операнда. Виртуальное наследование не учитывается.

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

Примечание

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

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

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

См. также PYTHONHASHSEED.

Изменено в версии 3.3: Случайное хеширование включено по умолчанию.

object.__bool__(self)

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

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

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

object.__getattr__(self, name)

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

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

object.__getattribute__(self, name)

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

Примечание

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

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

object.__setattr__(self, name, value)

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

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

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

object.__delattr__(self, name)

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

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

object.__dir__(self)

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

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

Специальные имена __getattr__ и __dir__ также могут использоваться для настройки доступа к атрибутам модуля. Функция __getattr__ на уровне модуля должна принимать одно аргумент — имя атрибута, и возвращать вычисленное значение или вызывать исключение AttributeError. Если атрибут не найден в объекте модуля через стандартный поиск, т.е. object.__getattribute__(), то __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__. Попытки присвоить переменную с несуществующим именем вызывают 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__.
  • Если для присвоения __slots__ используется dictionary, ключи словаря будут использоваться в качестве имён слотов. Значения словаря могут быть использованы для предоставления строковых описаний каждого атрибута, которые будут распознаны inspect.getdoc() и отображены в выводе help().
  • __class__ присваивание работает только если у обоих классов одинаковые __slots__.
  • Множественное наследование с несколькими родительскими классами с __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.

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 — Новый механизм супер

Описывает неявную __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 - Аннотации типов

Введение в механизм аннотаций типов 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(), которые ведут себя аналогично методам стандартных объектов Python dictionary. Модуль collections.abc предоставляет MutableMapping абстрактный базовый класс для создания этих методов на основе базового набора методов __getitem__(), __setitem__(), __delitem__() и keys(). Мутабельные последовательности должны предоставлять методы append(), count(), index(), extend(), insert(), pop(), remove(), reverse() и sort(), подобно стандартным объектам Python list. Наконец, типы последовательностей должны реализовывать сложение (т.е. конкатенацию) и умножение (т.е. повторение), определяя методы __add__(), __radd__(), __iadd__(), __mul__(), __rmul__() и __imul__(), описанные ниже; они не должны определять другие числовые операторы. Рекомендуется, чтобы как отображения, так и последовательности реализовывали метод __contains__() для эффективного использования оператора in; для отображений in должен просматривать ключи отображения; для последовательностей он должен просматривать значения.

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

object.__len__(self)

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

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

object.__length_hint__(self)

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

Введено в версии 3.4.

Примечание

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

a[1:2] = b

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

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

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

object.__getitem__(self, key)

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

Примечание

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

Примечание

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

object.__setitem__(self, key, value)

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

object.__delitem__(self, key)

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

object.__missing__(self, key)

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

object.__iter__(self)

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

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). Если конкретный метод не определён, расширенное присваивание использует обычные методы. Например, если x — экземпляр класса с методом __iadd__(), то x += y эквивалентно x = x.__iadd__(y). В противном случае рассматриваются 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. Поиск специальных методов

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

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

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

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

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

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

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

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

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

3.4. Корутины

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

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

Примечание

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

object.__await__(self)

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

Примечание

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

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

См. также

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

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

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

coroutine.close()

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

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

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

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

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

object.__aiter__(self)

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

object.__anext__(self)

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

Начиная с 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–2023 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.11/reference/datamodel.html

Spec-Zone.ru

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