Spec-Zone.ru › Python 3.10

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

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

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

None

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

NotImplemented

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

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

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

Ellipsis

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

numbers.Number

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

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

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

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

numbers.Integral

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

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

Integers (int)

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

Booleans (bool)

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

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

numbers.Real (float)

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

numbers.Complex (complex)

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

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

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

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

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

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

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

Строки

Строка — это последовательность значений, представляющих точки кода Юникода. Все точки кода в диапазоне 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().

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

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

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

Списки

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

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

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

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

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

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

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

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

Множества

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

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

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

Отображения

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

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

Словари

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

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

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

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

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

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

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

Определенные пользователем функции

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

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

Атрибут

Значение

__doc__

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

Записываемый

__name__

Имя функции.

Записываемый

__qualname__

Квалифицированное имя функции.

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

Записываемый

__module__

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

Записываемый

__defaults__

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

Записываемый

__code__

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

Записываемый

__globals__

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

Только для чтения

__dict__

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

Записываемый

__closure__

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

Только для чтения

__annotations__

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

Записываемый

__kwdefaults__

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

Записываемый

Большинство атрибутов, помеченных как «Записываемый», проверяют тип присваиваемого значения.

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

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

Дополнительную информацию об определении функции можно получить из ее объекта кода; см. описание внутренних типов ниже. Тип cell можно получить в модуле types.

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

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

Специальные атрибуты только для чтения: __self__ — объект экземпляра класса, __func__ — объект функции; __doc__ — документация метода (такая же как __func__.__doc__); __name__ — имя метода (такое же как __func__.__name__); __module__ — имя модуля, в котором был определен метод, или None если недоступно.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Встроенный объект функции является обёрткой вокруг функции C. Примерами встроенных функций являются len() и math.sin() (math — стандартный встроенный модуль). Количество и тип аргументов определяются функцией C. Специальные атрибуты только для чтения: __doc__ — строка документации функции, или None если недоступна; __name__ — имя функции; __self__ установлено в None (но см. следующий пункт); __module__ — имя модуля, в котором определена функция, или None если недоступно.

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

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

Классы

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

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

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

Модули

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

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

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

__name__

Имя модуля.

__doc__

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

__file__

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

__annotations__

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

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

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

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

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

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

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

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

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

__name__

Имя класса.

__module__

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

__dict__

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

__bases__

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

__doc__

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

__annotations__

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

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

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

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

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

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

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

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

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

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

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

Объекты кода

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

Специальные атрибуты только для чтения: co_name указывает имя функции; co_argcount — общее количество позиционных аргументов (включая позиционные-только аргументы и аргументы с значениями по умолчанию); co_posonlyargcount — количество позиционных-только аргументов (включая аргументы с значениями по умолчанию); co_kwonlyargcount — количество аргументов только по ключевым словам (включая аргументы с значениями по умолчанию); co_nlocals — количество локальных переменных, используемых функцией (включая аргументы); co_varnames — кортеж, содержащий имена локальных переменных (начиная с имен аргументов); co_cellvars — кортеж, содержащий имена локальных переменных, которые ссылаются на вложенные функции; co_freevars — кортеж, содержащий имена свободных переменных; co_code — строка, представляющая последовательность инструкций байткода; co_consts — кортеж, содержащий литералы, используемые байткодом; co_names — кортеж, содержащий имена, используемые байткодом; co_filename — имя файла, из которого был скомпилирован код; co_firstlineno — номер первой строки функции; co_lnotab — строка, кодирующая отображение ссылок байткода на номера строк (подробнее см. исходный код интерпретатора); co_stacksize — необходимый размер стека; co_flags — целое число, кодирующее количество флагов для интерпретатора.

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

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

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

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

Объекты фрейма

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

Специальные атрибуты только для чтения: f_back указывает предыдущий кадр стека (в сторону вызывающей функции) или None, если это нижний кадр стека; f_code — объект кода, выполняемого в этом кадре; f_locals — словарь, используемый для поиска локальных переменных; f_globals используется для глобальных переменных; f_builtins используется для встроенных (внутренних) имён; f_lasti указывает точную инструкцию (это индекс в строке байткода объекта кода).

Обращение к f_code вызывает событие аудита аудита object.__getattr__ с аргументами obj и "f_code".

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

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

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

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

frame.clear()

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

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

New in version 3.4.

Объекты стека исключений

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

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

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

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

Специальные атрибуты только для чтения: tb_frame указывает на кадр выполнения текущего уровня; tb_lineno указывает номер строки, где произошло исключение; tb_lasti указывает точную инструкцию. Номер строки и последняя инструкция в стеке исключений могут отличаться от номера строки объекта фрейма, если исключение произошло в инструкции try без соответствующего блока except или с блоком finally.

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

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

Изменено в версии 3.7: Объекты стека исключений теперь можно явно создавать из Python-кода, и атрибут tb_next существующих экземпляров можно обновлять.

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

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

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

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

slice.indices(self, length)

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

Статические объекты методов

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

object.__del__(self)

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

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

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

Примечание

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

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

См. также

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

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

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

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

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

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

object.__str__(self)

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

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

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

object.__bytes__(self)

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

object.__format__(self, format_spec)

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

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

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

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

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

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

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

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

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

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

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

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, они непредсказуемы при повторных запусках Python.

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

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

См. также PYTHONHASHSEED.

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

object.__bool__(self)

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

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

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

object.__getattr__(self, name)

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

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

object.__getattribute__(self, name)

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

Примечание

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

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

object.__setattr__(self, name, value)

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

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

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

object.__delattr__(self, name)

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

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

object.__dir__(self)

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

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

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

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

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

import sys
from types import ModuleType

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

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

sys.modules[__name__].__class__ = VerboseModule

Примечание

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

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

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

См. также

PEP 562 - Модуль __getattr__ и __dir__

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

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

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

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

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

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

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

object.__set__(self, instance, value)

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

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

object.__delete__(self, instance)

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

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

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

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

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

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

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

Прямой вызов

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

Привязка к экземпляру

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

Привязка к классу

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

Привязка через super

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

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

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

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

END_OF_DOCUMENT_MARKER

3.3.2.4. __slots__

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

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

object.__slots__

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

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

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

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

classmethod object.__init_subclass__(cls)

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

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

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

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

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

Примечание

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

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

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

object.__set_name__(self, owner, name)

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

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

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

class A:
   pass

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

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

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

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

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

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

class Meta(type):
    pass

class MyClass(metaclass=Meta):
    pass

class MySubclass(MyClass):
    pass

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

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

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

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

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

См. также

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

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

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

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

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

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

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

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

См. также

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

Введено __prepare__ хук пространства имён

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

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

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

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

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

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

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

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

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

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

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

См. также

PEP 3135 — Новый super

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

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

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

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

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

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

class.__instancecheck__(self, instance)

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

class.__subclasscheck__(self, subclass)

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

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

См. также

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

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

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

При использовании аннотаций типов, часто полезно параметризовать обобщенный тип с помощью квадратных скобок 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]. Для типов последовательностей допустимыми ключами должны быть целые числа и объекты срезов. Обратите внимание, что специальная интерпретация отрицательных индексов (если класс хочет эмулировать тип последовательности) зависит от метода __getitem__(). Если тип key не подходит, может быть поднято исключение TypeError; если значение key находится вне набора индексов для последовательности (после любой специальной интерпретации отрицательных значений), должно быть поднято исключение IndexError. Для типов отображений, если key отсутствует (не входит в контейнер), должно быть поднято исключение KeyError.

Примечание

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

Примечание

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

object.__setitem__(self, key, value)

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

object.__delitem__(self, key)

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

object.__missing__(self, key)

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

object.__iter__(self)

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

object.__reversed__(self)

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

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

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

object.__contains__(self, item)

Вызывается для реализации операторов проверки принадлежности. Должен вернуть true, если элемент находится в 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__(), вызывается x.__add__(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__(), вызывается y.__rsub__(x) если x.__sub__(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.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() или asyncio.coroutine(), также являются awaitable, но не реализуют __await__().

object.__await__(self)

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

Примечание

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

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

См. также

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

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.10/reference/datamodel.html

Spec-Zone.ru

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