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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Нет

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

NotImplemented

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

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

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

Эллипсис

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

numbers.Number

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

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

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

  • Представление ведется по основанию 10, когда это возможно.

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

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

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

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

numbers.Integral

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

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

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

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

Булевы (bool)

Они представляют истинностные значения False и True. Два объекта, представляющие значения False и True, являются единственными булевыми объектами. Тип Boolean является подтипом типа integer, и значения Boolean ведут себя как значения 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.

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

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

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

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

Струны

Строка - это последовательность значений, представляющих кодовые точки Unicode. Все кодовые точки в диапазоне U+0000 - U+10FFFF могут быть представлены в строке. В Python нет типа char; вместо этого каждая кодовая точка в строке представляется как строковый объект длиной 1. Встроенная функция ord() преобразует кодовую точку из строковой формы в целое число в диапазоне 0 - 10FFFF; chr() преобразует целое число в диапазоне 0 - 10FFFF в соответствующий строковый объект длины 1. str.encode() может использоваться для преобразования str в bytes с использованием заданной текстовой кодировки, а bytes.decode() может использоваться для достижения обратного результата.

Кортежи

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

Байты

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

Мутируемые последовательности

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

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

Списки

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

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

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

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

Типы комплектов

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

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

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

Устанавливает

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

Замороженные декорации

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

Отображения

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

Функция qualified name.

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

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

__module__

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

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

__defaults__

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

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

__code__

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

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

__globals__

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

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

__dict__

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

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

__closure__

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

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

__annotations__

Диктант, содержащий аннотации параметров. Ключами dict являются имена параметров, а 'return' - аннотация return, если она предусмотрена. Для получения дополнительной информации о работе с этим атрибутом смотрите Лучшие методы работы с аннотациями.

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

__kwdefaults__

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

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

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

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

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

Корутинные функции

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

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

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

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

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

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

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

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

Занятия

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

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

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

Модули

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

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

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

__name__

Имя модуля.

__doc__

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

__file__

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

__annotations__

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

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

CPython implementation detail: Из-за того, как 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__

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

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

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

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

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

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

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

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

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

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

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

Кодовые объекты

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

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

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

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

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

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

Рамочные объекты

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

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

Доступ к f_code вызывает auditing event object.__getattr__ с аргументами obj и "f_code".

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

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

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

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

frame.clear()

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

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

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

Отслеживание объектов

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

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

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

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

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

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

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

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

Нарезка объектов

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

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

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

slice.indices(self, length)

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

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

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

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

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

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

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

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

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

3.3.1. Базовая настройка

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

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

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

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

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

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

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

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

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

object.__del__(self)

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

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

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

Примечание

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

CPython implementation detail: It is possible for a reference cycle to prevent the reference count of an object from going to zero. In this case, the cycle will be later detected and deleted by the cyclic garbage collector. A common cause of reference cycles is when an exception has been caught in a local variable. The frame’s locals then reference the exception, which references its own traceback, which references the locals of all frames caught in the traceback.

См.также

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

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

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

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

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

object.__repr__(self)

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

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

object.__str__(self)

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

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

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

object.__bytes__(self)

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

object.__format__(self, format_spec)

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

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

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

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

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

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

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

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

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

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

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

object.__hash__(self)

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

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

Примечание

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

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

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

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

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

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

Примечание

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

Это предназначено для обеспечения защиты от отказа в обслуживании, вызванного тщательно подобранными входными данными, которые используют наихудшую производительность вставки диктанта, сложность O(n2). Подробности см. на http://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).

Примечание

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

Вызывает auditing event object.__getattr__ с аргументами obj, name.

object.__setattr__(self, name, value)

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

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

Вызывает auditing event object.__setattr__ с аргументами obj, name, value.

object.__delattr__(self, name)

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

Вызывает auditing event object.__delattr__ с аргументами obj, name.

object.__dir__(self)

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

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

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

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

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

import sys
from types import ModuleType

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

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

sys.modules[__name__].__class__ = VerboseModule

Примечание

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

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

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

См.также

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

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

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

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

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

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

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

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

3.3.2.4. __слоты__

__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__, не поддерживают weak references к своим экземплярам. Если поддержка слабых ссылок необходима, то добавьте '__weakref__' к последовательности строк в объявлении __slots__.

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

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

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

  • Непустые __slots__ не работают для классов, производных от встроенных типов «переменной длины», таких как int, bytes и tuple.

  • Любая нестрока iterable может быть назначена на __slots__.

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

  • Назначение __class__ работает, только если оба класса имеют одинаковые __slots__.

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

  • Если для __slots__ используется iterator, то для каждого значения итератора создается descriptor. Однако атрибут __slots__ будет пустым итератором.

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

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

classmethod object.__init_subclass__(cls)

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

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

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

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

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

Примечание

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

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

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

object.__set_name__(self, owner, name)

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

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

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

class A:
   pass

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

Более подробную информацию см. в разделе Создание объекта класса.

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

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

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

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

class Meta(type):
    pass

class MyClass(metaclass=Meta):
    pass

class MySubclass(MyClass):
    pass

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

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

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

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

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

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

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

3.3.3.2. Урегулирование записей по ТОиР

Если база, фигурирующая в определении класса, не является экземпляром 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 implementation detail: В CPython 3.6 и более поздних версиях ячейка __class__ передается в метакласс как запись __classcell__ в пространстве имен класса. Если она присутствует, она должна быть распространена до вызова type.__new__, чтобы класс был инициализирован правильно. Если этого не сделать, то в Python 3.8 это приведет к ошибке RuntimeError.

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

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

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

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

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

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

См.также

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

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

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

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

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

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

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

class.__instancecheck__(self, instance)

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

class.__subclasscheck__(self, subclass)

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

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

См.также

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

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

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

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

См.также

PEP 484 - Подсказки типа

Знакомство с основой Python для аннотаций типов

Generic Alias Types

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

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

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

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

classmethod object.__class_getitem__(cls, key)

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

Если метод определен для класса, __class_getitem__() автоматически является методом класса. Поэтому при его определении нет необходимости украшать его символом @classmethod.

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

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

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

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

3.3.5.2. __class_getitem__ против __getitem__.

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

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

from inspect import isclass

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

    class_of_obj = type(obj)

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

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

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

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

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

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

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

См.также

PEP 560 - Ядро Поддержка типизации модульных и общих типов

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

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

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

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

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

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

object.__len__(self)

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

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

object.__length_hint__(self)

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

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

Примечание

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

a[1:2] = b

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

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

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

object.__getitem__(self, key)

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

Примечание

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

Примечание

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

object.__setitem__(self, key, value)

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

object.__delitem__(self, key)

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

object.__missing__(self, key)

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

object.__iter__(self)

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

object.__reversed__(self)

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

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

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

object.__contains__(self, item)

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

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

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

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

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

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

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

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

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

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

Примечание

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

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

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

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

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

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

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

object.__index__(self)

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

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

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

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

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

3.3.9. С менеджерами по контексту заявлений

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

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

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

object.__enter__(self)

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

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

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

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

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

См.также

PEP 343 - Утверждение «с»

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

3.3.10. Настройка позиционных аргументов при сопоставлении шаблонов классов

При использовании имени класса в шаблоне позиционные аргументы в шаблоне по умолчанию не допускаются, т.е. case MyClass(x, y) обычно недопустимо без специальной поддержки MyClass. Чтобы иметь возможность использовать такого рода шаблоны, класс должен определить атрибут __match_args__.

object.__match_args__

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

Например, если MyClass.__match_args__ является ("left", "center", "right"), это означает, что case MyClass(x, y) эквивалентно case MyClass(left=x, center=y). Обратите внимание, что количество аргументов в шаблоне должно быть меньше или равно количеству элементов в __match_args__; если оно больше, то попытка сопоставления шаблона приведет к ошибке TypeError.

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

См.также

PEP 634 - Структурное сопоставление шаблонов

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

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

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

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

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

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

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

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

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

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

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

3.4. Корутины

3.4.1. Ожидаемые объекты

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

Примечание

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

object.__await__(self)

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

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

См.также

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

3.4.2. Объекты Coroutine

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

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

Изменено в версии 3.5.2: Ожидать выполнения coroutine более одного раза - это RuntimeError.

coroutine.send(value)

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

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

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

coroutine.close()

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

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

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

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

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

object.__aiter__(self)

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

object.__anext__(self)

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

Пример асинхронного итерируемого объекта:

class Reader:
    async def readline(self):
        ...

    def __aiter__(self):
        return self

    async def __anext__(self):
        val = await self.readline()
        if val == b'':
            raise StopAsyncIteration
        return val

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

Изменено в версии 3.7: До Python 3.7 функция __aiter__() могла возвращать awaitable, который разрешался в asynchronous iterator.

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

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

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

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

object.__aenter__(self)

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

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

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

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

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

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

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

Сноски

1

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

2

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

3

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

4

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

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