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

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

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

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

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

Тип объекта определяет операции, которые поддерживает объект (например, «есть ли у него длина?»), а также определяет возможные значения для объектов этого типа. Функция type() возвращает тип объекта (который является тоже объектом). Как его идентификатор, 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. Используется для обозначения отсутствия значения во многих ситуациях, например, он возвращается функцией, которые ничего явно не возвращают. Его булево значение — False.

NotImplemented

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

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

Многоточие

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

numbers.Number

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

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

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

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

numbers.Integral

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

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

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

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

Они представляют булевы значения Ложь и Истина. Два объекта, представляющие значения 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 нет типа c:type:char; вместо этого, каждая кодовая точка в строке представлена как строковый объект длиной 1. Встроенная функция ord() преобразует кодовую точку из строки в целое число в диапазоне 0 - 10FFFF; chr() преобразовывает целое число в диапазоне 0 - 10FFFF к соответствующему строковому объекту длины 1. str.encode() может использоваться, чтобы преобразовать str в bytes с использованием заданной текстовой кодировки, а bytes.decode() может использоваться, для достижения противоположного.

Кортежи

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

Байты

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

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

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

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

Списки

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

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

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

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

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

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

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

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

Множества

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

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

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

Отображения

Они представляют собой конечные наборы объектов, индексированных произвольными множествами индексов. Индексное обозначение 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__ dict, содержащий аннотации параметров. Ключи dict - названия параметров и 'return' для возвращения аннотации, если передан. Перезаписываемый
__kwdefaults__ dict содержащий параметры по умолчанию только для ключевых параметров. Перезаписываемый

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

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

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

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

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

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

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

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

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

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

Специальные атрибуты: __name__ - имя класса; __module__ - имя модуля, в котором был определен класс; __dict__ - словарь, содержащий пространство имён класса; __bases__ - кортеж, содержащий базовые классы в порядке их появления в списке базовых классов; __doc__ - строка документации класса или None, если она не определена; __annotations__ (необязательный) - словарь, содержащий аннотации переменных, собранные во время выполнения тела класса.

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

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

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

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

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

I/O объекты (также известные как файловые объекты)

Файловый объект представляет собой открытый файл. Для создания файловых объектов доступны различные ярлыки: встроенная функция 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 устанавливается, если функция была собрана с включенным будущим делением (future division); биты 0x10 и 0x1000 использовались в более ранних версиях Python.

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

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

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

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

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

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

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

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

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

frame.clear()

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

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

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

Объекты трейсбэка

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

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

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

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

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

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

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

Объекты нарезки (slice)

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

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

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

slice.indices(self, length)

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

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

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

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

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

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

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

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

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

Примечание

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

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

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

object.__getattribute__(self, name)

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

Примечание

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

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

object.__setattr__(self, name, value)

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

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

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

object.__delattr__(self, name)

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

Для удаления определенных чувствительных атрибутов вызывается событие аудита object.__getattr__ с аргументами 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’а поддерживают данную спецификацию; однако, вероятно, некоторые сторонние инструменты содержат дескрипторы, которые требуют обоих аргументов. Собственная реализация Python’а __getattribute__(), всегда передает оба аргумента независимо от того, требуются они или нет.

object.__set__(self, instance, value)

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

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

object.__delete__(self, instance)

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

object.__set_name__(self, owner, name)

Вызывается во время создания владельца класса owner. Дескриптору присваивается имя name.

Примечание

__set_name__() вызывается только неявно как часть конструктора type, поэтому его необходимо вызвать явно с соответствующими параметрами, когда дескриптор добавляется к классу после первоначального создания:

class A:
   pass
descr = custom_descriptor()
A.attr = descr
descr.__set_name__(A, 'attr')

Дополнительные сведения см. в разделе Создание объекта класса.

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

Атрибут __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).
Супер-привязка,
Если 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__() метод. Дескрипторы данных с заданными __set__() и __get__() всегда переопределяют переопределение в словаре экземпляра. напротив, дескрипторы, не связанные с данными, могут быть переопределены экземпляром.

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

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

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__. Попытки присвоить имя переменной, не указанной в списке, вызывают ошибку AttributeError. Если требуется динамическое присвоение новых переменных, добавьте '__dict__' к последовательности строк в объявлении __slots__.
  • Без переменной __weakref__ для каждого случая классы, определяющие __slots__, не поддерживают слабые ссылки на его сущности. Если требуется слабая опорная поддержка, добавьте '__weakref__' в последовательность строки в объявлении __slots__.
  • __slots__ реализуются на уровне класса путем создания дескрипторов (Реализация дескрипторов) для каждого имени переменной. В результате атрибуты класса не могут использоваться для установки значений по умолчанию для переменных определенных __slots__ экземпляра, ; в противном случае атрибут класса перезаписывает назначение дескриптора.
  • Действие объявления __slots__ не ограничивается классом, в котором оно определено. __slots__, объявленные у родителей, доступны в дочерних классах. Однако дочерние подклассы получат __dict__ и __weakref__, если они также не определят __slots__ (который должен содержать только имена любых дополнительных слотов).
  • Если класс определяет слот, также определенный в базовом классе, переменная экземпляра, определенная слотом базового класса, становится недоступна (кроме как путем получения ее дескриптора непосредственно из базового класса). Это делает значение программы неопределенным. В будущем может быть добавлена проверка, для предотвращения этого.
  • Непустой __slots__ не работает для классов, производных от встроенных типов переменной длины, таких как int, bytes и tuple.
  • Любой нестроковый итерируемый объект может быть присвоен в __slots__. Могут также использоваться сопоставления; однако, в будущих значениях, соответствующих каждому ключу, может быть присвоено особое значение.
  • Присвоение __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.

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__, чтобы класс был правильно инициализирован. В противном случае в Python 3.8 возникнет ошибка RuntimeError.

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

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

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

class.__subclasscheck__(self, subclass)

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

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

См.также

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

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

Можно реализовать синтаксис универсального класса, как определено в PEP 484 (например, List[int]), путём определения специального метода:

classmethod object.__class_getitem__(cls, key)

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

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

См.также

PEP 560 - поддержка ядром типизации модулей и универсальных типов

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

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

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

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

Следующие методы могут быть определены для реализации контейнерных объектов. Контейнеры обычно представляют собой последовательности (например, списки или кортежи) или сопоставления (например, словари), но могут также представлять другие контейнеры. Первый набор методов используется либо для имитации последовательности, либо для имитации отображения; разница в том, что для последовательности допустимыми ключами должны быть целые числа k, для которых, 0 <= k < N где N - длина последовательности или объекты среза, которые определяют диапазон элементов. Также рекомендуется, чтобы отображения реализовывали методы keys(), values(), items(), get(), clear(), setdefault(), pop(), popitem(), copy(), update(); аналогичное поведению для стандартных объектов словаря Python’а. Модуль collections.abc предоставляет абстрактный базовый класс MutableMapping, чтобы помочь создать эти методы из базового набора __getitem__(), __setitem__(), __delitem__() и keys(). Изменяемые последовательности должны реализовывать методы append(), count(), index(), extend(), insert(), pop(), remove(), reverse() и sort(), как стандартные объекты списка Python. Наконец, типы последовательностей должны реализовать сложение (т.е. конкатенацию) и умножение (т.е. повторение), определив методы __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; если значение выходит за пределы набора индексов для последовательности (после любой специальной интерпретации отрицательных значений), следует вызвать IndexError. Для типов сопоставления, если key отсутствует (не в контейнере), следует вызвать KeyError.

Примечание

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

object.__setitem__(self, key, value)

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

object.__delitem__(self, key)

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

object.__missing__(self, key)

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

object.__iter__(self)

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

Объекты-итераторы также должны реализовать этот метод; они обязаны вернуться сами. Дополнительные сведения об объектах-итераторах см. в разделе Типы итератора.

object.__reversed__(self)

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

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

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

object.__contains__(self, item)

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

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

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

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

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

Эти методы вызваются для реализации бинарных арифметических операций (+,``-, ``*, @, /, //, %, divmod(), pow(), **, <<, >>, &, ^, |). Например, чтобы вычислить выражение x + y, где x сущность класса у которого есть метод __add__(), вызывается x.__add__(y). Метод __divmod__() должен быть эквивалентен использованию __floordiv__' и :meth:`__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__() не определено, то встроенная функция int() возвращается к __trunc__().

3.3.9. Оператор with контекстных менеджеров

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

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

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

object.__enter__(self)

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

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

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

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

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

См.также

PEP 343 - оператор «with»
Cпецификация, предыстория и примеры для Python оператора with.

3.3.10. Специальный метод поиска

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

>>> 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("Вызван метакласс getattribute")
...         return type.__getattribute__(*args)
...
>>> class C(object, metaclass=Meta):
...     def __len__(self):
...         return 10
...     def __getattribute__(*args):
...         print("Вызван класс getattribute")
...         return object.__getattribute__(*args)
...
>>> c = C()
>>> c.__len__()                 # Явный поиск через сущность
Class getattribute invoked
10
>>> type(c).__len__(c)          # Явный поиск через тип
Metaclass getattribute invoked
10
>>> len(c)                      # Неявный поиск
10

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

3.4. Корутины

3.4.1. Await объекты

Awaitable объект обычно реализует метод __await__(). Объекты корутины, возвращенные из функций async def — awaitable.

Примечание

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

object.__await__(self)

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

Добавлено в версии 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(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('Вход в контекст')

    async def __aexit__(self, exc_type, exc, tb):
        await log('Выход из контекста')

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

Сноски

[1]В некоторых случаях возможно изменить тип объекта при определенных контролируемых условиях. Как правило, это не лучшая идея, поскольку при неправильном обращении может привести к очень странному поведению.
[2]Методы __hash__(), __iter__(), __reversed__() и __contains__() имеют для этого специальную обработку; другие по-прежнему будут поднимать TypeError, но могут сделать это, полагаясь на поведение, что None не вызывается.
[3]«Не поддерживает» здесь означает, что класс не имеет такого метода или метод возвращает NotImplemented. Не устанавливайте для метода значение None, если требуется принудительно использовать метод, отраженный в правом операнде. Вместо этого будет явно блокироваться такой метод.
[4]Для операндов того же типа предполагается, что если неотражённый метод (например, __add__()) завершается неудачно, то общая операция не поддерживается, поэтому отраженный метод не вызывается.