3. Модель данных¶
3.1. Объекты, значения и типы данных¶
Объекты — это абстракция данных в Python. Все данные в программе Python представлены объектами или отношениями между ними. Даже код представлен объектами.
Каждый объект имеет идентификатор, тип и значение. Идентификатор объекта никогда не меняется после его создания; его можно рассматривать как адрес объекта в памяти. Оператор is сравнивает идентификаторы двух объектов, а функция id() возвращает его в виде целого числа.
Для CPython, id(x) — это адрес памяти, где хранится x.
Тип объекта определяет операции, которые поддерживает этот объект (например, «имеет ли он длину?»), а также задаёт возможные значения для объектов этого типа. Функция type() возвращает тип объекта (который сам является объектом). Как и идентификатор, тип объекта также неизменен. [1]
Значение некоторых объектов может изменяться. Такие объекты называются изменяемыми. И наоборот, объекты, значение которых нельзя изменить после создания, называются неизменяемыми. (Значение неизменяемого контейнера, содержащего ссылки на изменяемые объекты, может изменяться, когда значения последних изменяются. Однако такой контейнер всё равно считается неизменяемым, поскольку нельзя изменить коллекцию объектов, которые он содержит. Таким образом, неизменяемость не полностью совпадает с понятием неизменяемого значения, это более тонкое понятие.) Изменяемость объекта определяется его типом. Например, числа, строки и кортежи — неизменяемы, а словари и списки — изменяемы.
Объекты никогда не уничтожаются явно. Однако, когда они становятся ненужными, они могут быть удалены сборщиком мусора. Реализация может откладывать сборку мусора или вовсе её не выполнять — это зависит от качества реализации, главное, чтобы не удалялись объекты, к которым ещё есть доступ.
CPython в настоящее время использует схему подсчёта ссылок с (опциональным) отложенным обнаружением циклически связанных ненужных элементов, что позволяет собирать большинство объектов сразу после того, как они становятся неиспользуемыми, но не гарантирует сборку мусора, содержащего циклические ссылки. Смотрите документацию модуля gc для информации о контроле сбора циклического мусора. Другие реализации работают иначе, а CPython может измениться. Не следует полагаться на немедленную финальную обработку объектов при их недостижимости (поэтому файлы всегда следует закрывать явно).
Заметьте, что использование конкретных средств трассировки или отладки может удерживать объекты живыми, которые в обычных условиях были бы собраны. Также имейте в виду, что перехват исключений в инструкциях try…except может удерживать объекты живыми.
Некоторые объекты содержат ссылки на «внешние» ресурсы, такие как открытые файлы или окна. Разумеется, эти ресурсы освобождаются при удалении объекта сборщиком мусора. Но поскольку сборка мусора не гарантируется, такие объекты также предоставляют явный способ освободить внешний ресурс, обычно через метод close(). Настоятельно рекомендуется явно закрывать такие объекты. Инструкции try…finally и with предоставляют удобные способы сделать это.
Некоторые объекты содержат ссылки на другие объекты. Они называются контейнерами. Примеры контейнеров: кортежи, списки и словари. Эти ссылки являются частью значения контейнера. В большинстве случаев, когда мы говорим о значении контейнера, подразумеваются значения, а не идентификаторы содержащихся объектов. Однако при обсуждении изменяемости контейнера подразумеваются только идентификаторы объектов, непосредственно содержащихся в нём. Таким образом, если неизменяемый контейнер (например, кортеж) содержит ссылку на изменяемый объект, его значение меняется, если изменяется содержимое этого изменяемого объекта.
Типы влияют практически на все аспекты поведения объектов. Даже значение идентификатора объекта в некотором смысле зависит от типа: для неизменяемых типов операции, вычисляющие новые значения, могут на самом деле возвращать ссылку на существующий объект с тем же типом и значением, тогда как для изменяемых объектов это не разрешено. Например, после a = 1; b = 1, a и b могут ссылаться на один и тот же объект со значением один или на разные объекты, в зависимости от реализации. Это происходит потому, что int — неизменяемый тип, поэтому ссылка на 1 может быть переиспользована. Такое поведение зависит от используемой реализации и не должно восприниматься как гарантированное, но его стоит учитывать при проверках идентичности объектов. Однако после c = []; d = [], c и d гарантированно ссылаются на два различных, уникальных, заново созданных пустых списка. (Обратите внимание, что e = f = [] присваивает один и тот же объект и e, и f.)
3.2. Иерархия стандартных типов¶
Ниже приведён список типов, встроенных в Python. Модули расширений (написанные на C, Java или других языках, в зависимости от реализации) могут определять дополнительные типы. В будущих версиях Python в иерархию типов могут быть добавлены новые типы (например, рациональные числа, эффективно хранимые массивы целых чисел и т. п.), хотя такие дополнения чаще будут предоставляться через стандартную библиотеку.
В описании некоторых типов ниже приведён абзац со списком «специальных атрибутов». Это атрибуты, которые предоставляют доступ к деталям реализации и не предназначены для общего использования. Их определение может измениться в будущем.
3.2.1. None¶
У этого типа есть только одно значение. Существует единственный объект с этим значением. Этот объект доступен через встроенное имя None. Он используется для обозначения отсутствия значения во многих случаях, например, возвращается функциями, которые явно ничего не возвращают. Его логическое значение — ложь.
3.2.2. NotImplemented¶
У этого типа есть только одно значение. Существует единственный объект с этим значением. Этот объект доступен через встроенное имя NotImplemented. Числовые методы и методы расширенного сравнения должны возвращать это значение, если они не реализуют операцию для данных операндов. (Интерпретатор затем попробует отражённую операцию или другой вариант обработки, в зависимости от оператора.) Его не следует использовать в логическом контексте.
См. Implementing the arithmetic operations для получения подробностей.
Изменено в версии 3.9: Использование NotImplemented в логическом контексте было объявлено устаревшим.
Изменено в версии 3.14: Использование NotImplemented в логическом контексте теперь возбуждает TypeError. Ранее оно оценивалось как True и генерировало DeprecationWarning начиная с Python 3.9.
3.2.3. Ellipsis¶
У этого типа есть только одно значение. Существует единственный объект с этим значением. Этот объект доступен через литерал ... или через встроенное имя Ellipsis. Его логическое значение — истина.
3.2.4. numbers.Number¶
Они создаются числовыми литералами и возвращаются как результаты арифметических операторов и встроенных арифметических функций. Числовые объекты неизменяемы: после создания их значение никогда не меняется. Числа в Python, разумеется, тесно связаны с математическими числами, но подчиняются ограничениям численного представления в компьютерах.
Строковые представления числовых классов, вычисляемые методами __repr__() и __str__(), обладают следующими свойствами:
Они являются корректными числовыми литералами, которые при передаче в конструктор своего класса создают объект со значением исходного числа.
Представление, когда это возможно, осуществляется в десятичной системе счисления.
Ведущие нули, за исключением, возможно, одного нуля перед десятичной точкой, не отображаются.
Конечные нули, за исключением, возможно, одного нуля после десятичной точки, не отображаются.
Знак отображается только в том случае, если число отрицательное.
Python различает целые числа, числа с плавающей точкой и комплексные числа:
3.2.4.1. numbers.Integral¶
Эти объекты представляют элементы математического множества целых чисел (положительных и отрицательных).
Примечание
Правила представления целых чисел выбраны так, чтобы операции сдвига и наложения маски имели наиболее осмысленную интерпретацию, в том числе для отрицательных чисел.
Существует два типа целых чисел:
- Целые числа (
int) Они представляют числа неограниченного диапазона, ограниченного лишь объёмом доступной (виртуальной) памяти. Для операций сдвига и наложения маски предполагается двоичное представление, а отрицательные числа представляются в варианте дополнительного до степени 2 кода, создающем иллюзию бесконечной последовательности значащих битов, продолжающейся влево.
- Логические значения (
bool) Они представляют логические значения Ложь и Истина. Два объекта, представляющие значения
FalseиTrue, являются единственными логическими объектами. Логический тип является подтипом целых чисел, и логические значения ведут себя как числа 0 и 1 соответственно почти во всех контекстах, за исключением случая преобразования их в строки"False"и"True"соответственно.
3.2.4.2. numbers.Real (float)¶
Они представляют числа с плавающей точкой двойной точности на машинном уровне. Диапазон допустимых значений и обработка переполнения зависят от архитектуры машины (и реализации на C или Java). Python не поддерживает числа с плавающей точкой одинарной точности — экономия процессорного времени и памяти, ради которой их обычно используют, ничтожна по сравнению с накладными расходами на использование объектов в Python. Поэтому нет смысла усложнять язык двумя видами чисел с плавающей точкой.
3.2.4.3. numbers.Complex (complex)¶
Они представляют комплексные числа как пару чисел с плавающей точкой двойной точности на машинном уровне. Здесь действуют те же оговорки, что и для чисел с плавающей точкой. Вещественную и мнимую части комплексного числа z можно получить через атрибуты только для чтения z.real и z.imag.
3.2.5. Последовательности¶
Последовательности представляют конечные упорядоченные множества, индексируемые неотрицательными числами. Встроенная функция len() возвращает количество элементов последовательности. Если длина последовательности равна n, множество индексов содержит числа 0, 1, …, n-1. Элемент i последовательности a выбирается с помощью a[i]. Некоторые последовательности, включая встроенные, интерпретируют отрицательные индексы путём прибавления к ним длины последовательности. Например, a[-2] эквивалентно a[n-2] — предпоследнему элементу последовательности a длины n.
Полученное значение должно быть неотрицательным целым числом, меньшим количества элементов в последовательности. Если это не так, возбуждается исключение IndexError.
Последовательности также поддерживают срезы: a[start:stop] выбирает все элементы с индексом k, такие что start <= k < stop. При использовании в качестве выражения срез представляет собой последовательность того же типа. Приведённое выше замечание об отрицательных индексах также относится к отрицательным границам срезов. Обратите внимание, что ошибка не возникает, если граница среза меньше нуля или больше длины последовательности.
Если параметр start отсутствует или равен None, он считается равным нулю. А если не указан или равен None параметр stop, то он считается равным длине последовательности.
Некоторые последовательности также поддерживают «расширенные срезы» с третьим параметром «шага»: a[i:j:k] выбирает все элементы a с индексом x, где x = i + n*k, n >= 0 и i <= x < j.
Последовательности различаются по изменяемости.
3.2.5.1. Неизменяемые последовательности¶
Объект типа неизменяемой последовательности не может измениться после создания. (Если объект содержит ссылки на другие объекты, эти другие объекты могут быть изменяемыми и могут изменяться; однако коллекция объектов, на которые непосредственно ссылается неизменяемый объект, не может измениться.)
Следующие типы являются неизменяемыми последовательностями:
- Строки
Строка (
str) — это последовательность значений, представляющих символы или, более формально, кодовые точки Юникод. Все кодовые точки в диапазоне от0до0x10FFFFмогут быть представлены в строке.В Python нет отдельного типа символ. Вместо этого каждая кодовая точка в строке представлена объектом строки длиной
1.Встроенная функция
ord()преобразует кодовую точку из строкового представления в целое число из диапазона от0до0x10FFFF;chr()преобразует целое число из диапазона от0до0x10FFFFв соответствующий объект строки длиной1. Методstr.encode()можно использовать для преобразованияstrвbytesс использованием указанной кодировки текста, аbytes.decode()позволяет выполнить обратное преобразование.- Кортежи
Элементы
tupleмогут быть произвольными объектами Python. Кортежи из двух и более элементов создаются списками выражений, разделённых запятыми. Кортеж из одного элемента (так называемый «одноэлементный кортеж») создаётся добавлением запятой после выражения (само по себе выражение не создаёт кортеж, поскольку круглые скобки должны оставаться доступными для группировки выражений). Пустой кортеж создаётся пустой парой круглых скобок.- Байты
Объект
bytesявляется неизменяемым массивом. Его элементы — это 8-битные байты, представленные целыми числами из диапазона 0 <= x < 256. Литералы байтов (например,b'abc') и встроенный конструкторbytes()можно использовать для создания объектов bytes. Кроме того, объекты bytes можно декодировать в строки с помощью методаdecode().
3.2.5.2. Изменяемые последовательности¶
Изменяемые последовательности можно изменять после их создания. Выражение с доступом к элементу или взятием среза можно использовать в качестве цели присваивания и инструкции del (удаления).
Примечание
Модули collections и array предоставляют дополнительные примеры типов изменяемых последовательностей.
В настоящее время существует два внутренних типа изменяемых последовательностей:
- Списки
Элементы списка могут быть произвольными объектами Python. Списки формируются размещением списка выражений через запятую в квадратные скобки. (Обратите внимание, что для создания списков длиной 0 или 1 не требуется никаких особых правил.)
- Массивы байтов
Объекты bytearray представляют собой изменяемые массивы. Они создаются встроенным конструктором
bytearray(). Помимо того, что байтовые массивы изменяемы (и, следовательно, не хэшируются), в остальном они предоставляют тот же интерфейс и функциональность, что и неизменяемые объектыbytes.
3.2.6. Типы множеств¶
Они представляют собой неупорядоченные конечные наборы уникальных неизменяемых объектов. Так что, они не могут быть проиндексированы каким-либо индексатором. Однако их можно перебирать, а встроенная функция len() возвращает количество элементов в наборе. Обычно наборы используются для быстрой проверки принадлежности, удаления дубликатов из последовательности и выполнения математических операций, таких как пересечение, объединение, разность и симметричная разность.
Для элементов множества действуют те же правила неизменяемости, что и для ключей словаря. Обратите внимание, что числовые типы подчиняются обычным правилам сравнения чисел: если два числа равны при сравнении (например, 1 и 1.0), в множестве может содержаться только одно из них.
В настоящее время существуют два встроенных типа множеств:
- Множества
Они представляют собой изменяемые множества. Множества создаются встроенным конструктором
set()и впоследствии могут изменяться с помощью различных методов, таких какadd().- Замороженные множества
Они представляют собой неизменяемые множества. Неизменяемые множества создаются встроенным конструктором
frozenset(). Поскольку такое множество является неизменяемым и хешируемым, его можно использовать как элемент другого множества или как ключ словаря.
3.2.7. Отображения¶
Они представляют собой конечные множества объектов, индексированных произвольными наборами индексов. Обращение к элементу в виде a[k] выбирает из отображения a элемент, соответствующий индексатору k. Такое обращение можно использовать в выражениях, а также в качестве цели присваивания или инструкции del. Встроенная функция len() возвращает количество элементов в отображении.
Есть два встроенных типа отображений:
3.2.7.1. Словари¶
Они представляют собой конечные множества объектов, индексированных почти произвольными значениями. В качестве ключей нельзя использовать только значения, содержащие списки, словари или другие изменяемые типы, которые сравниваются по значению, а не по идентификатору объектов, поскольку эффективная реализация словарей требует, чтобы хэш-значение ключа оставалось неизменным. Числовые типы, используемые в качестве ключей, подчиняются обычным правилам сравнения чисел: если два числа равны при сравнении (например, 1 и 1.0), их можно взаимозаменяемо использовать для индексации одной и той же записи словаря.
Словари сохраняют порядок вставки, то есть при переборе словаря ключи возвращаются в том же порядке, в котором они были добавлены. Замена значения, связанного с существующим ключом, не меняет порядок, однако удаление элемента по ключу и его повторная вставка перемещают ключ в конец, а не возвращают его на прежнее место.
Словари изменяемы; они могут быть созданы с помощью нотации {} (см. раздел Dictionary displays).
Модули расширения dbm.ndbm и dbm.gnu предоставляют дополнительные примеры типов отображения, как и модуль collections.
Изменено в версии 3.7: Словари не сохраняли порядок вставки в версиях Python до 3.6. В CPython 3.6 порядок вставки сохранялся, но в то время это считалось деталью реализации, а не гарантией языка.
3.2.7.2. Замороженные словари¶
Они представляют собой неизменяемые словари. Они создаются с помощью встроенного конструктора frozendict(). Такой словарь является хешируемым, если все его ключи и значения хэшируемы. В этом случае его можно использовать как элемент множества или как ключ другого отображения. frozendict не является подклассом dict; он непосредственно наследует от object.
Добавлено в версии 3.15.
3.2.8. Вызываемые типы¶
Это типы, к которым может применяться операция вызова функции (см. раздел Calls):
3.2.8.1. Пользовательские функции¶
Объект пользовательской функции создаётся определением функции (см. раздел Function definitions). При вызове ему следует передавать список аргументов, содержащий столько же элементов, сколько формальных параметров у функции.
3.2.8.1.1. Специальные атрибуты, доступные только для чтения¶
Атрибут |
Значение |
|---|---|
|
Ссылка на Добавлено в версии 3.10. |
|
Ссылка на |
|
Объект ячейки имеет атрибут |
3.2.8.1.2. Специальные атрибуты, доступные для записи¶
Большинство этих атрибутов проверяют тип присваиваемого значения:
Атрибут |
Значение |
|---|---|
|
Строка документации функции или |
|
Имя функции. См. также: |
|
Квалифицированное имя функции. См. также: Добавлено в версии 3.3. |
|
Имя модуля, в котором была определена функция, или |
|
|
|
Объект кода, представляющий скомпилированное тело функции. |
|
Пространство имён, поддерживающее произвольные атрибуты функции. См. также: |
|
Изменено в версии 3.14: Теперь аннотации вычисляются лениво. См. PEP 649. |
|
Функция аннотации для этой функция или Добавлено в версии 3.14. |
|
|
|
Добавлено в версии 3.12. |
Объекты функций также позволяют читать и изменять произвольные атрибуты, которые можно использовать, например, для добавления к функциям метаданных. Для чтения и изменения таких атрибутов используется обычная точечная нотация атрибутов.
Текущая реализация CPython поддерживает атрибуты функций только у пользовательских функций. В будущем атрибуты функций могут поддерживаться и у встроенных функций.
Дополнительную информацию об определении функции можно получить из её объекта кода (доступного через атрибут __code__).
3.2.8.2. Методы экземпляра¶
Объект метода экземпляра объединяет класс, экземпляр класса и любой вызываемый объект (обычно определяемую пользователем функцию).
Специальные атрибуты, доступные только для чтения:
|
Ссылается на объект экземпляра класса, к которому метод привязан. |
|
Ссылается на исходный объект функции. |
|
Документация метода (то же, что и |
|
Имя метода (то же, что и |
|
Имя модуля, в котором был определён метод, или |
Методы также позволяют получать доступ к произвольным атрибутам (но не изменять их) лежащего в их основе объекта функции.
Объекты пользовательских методов могут создаваться при обращении к атрибуту класса (в том числе через экземпляр этого класса), если этот атрибут является объектом пользовательской функции или объектом classmethod.
Когда объект метода экземпляра создаётся при получении объекта пользовательской функции из класса через один из его экземпляров, его атрибут __self__ является этим экземпляром, а сам объект метода называется привязанным. Атрибут __func__ нового метода является исходным объектом функции.
Когда объект метода экземпляра создаётся при получении объекта classmethod из класса или экземпляра, его атрибут __self__ фактически является самим классом, а атрибут __func__ — объектом функции, лежащей в основе метода класса.
При вызове объекта метода экземпляра вызывается лежащая в его основе функция (__func__), причём экземпляр класса (__self__) вставляется в начало списка аргументов. Например, если C — класс, содержащий определение функции f(), а x — экземпляр C, то вызов x.f(1) эквивалентен вызову C.f(x, 1).
Если объект метода экземпляра создан на основе объекта classmethod, то «экземпляр класса», хранящийся в __self__, фактически является самим классом. Поэтому вызов x.f(1) или C.f(1) эквивалентен вызову f(C,1), где f — лежащая в основе функция.
Важно отметить, что определяемые пользователем функции, являющиеся атрибутами экземпляра класса, не преобразуются в привязанные методы. Такое преобразование происходит только если функция является атрибутом класса.
3.2.8.3. Генераторные функции¶
Функция или метод, в которых содержится выражение yield (см. раздел Yield expressions), называются генераторной функцией. При вызове такая функция всегда возвращает объект итератора, который можно использовать для выполнения тела функции. Вызов метода iterator.__next__() приводит к выполнению функции до тех пор, пока она не выдаст значение с помощью выражения yield. Когда функция выполняет инструкцию return или выполнение доходит до конца функции, возникает исключение StopIteration, указывающее на исчерпание итератора: он больше не предоставляет новых значений.
3.2.8.4. Сопрограммные функции¶
Функция или метод, определённые с помощью async def, называются сопрограммными функциями. При вызове такая функция возвращает объект сопрограммы. Она может содержать выражения await, а также инструкции async with и async for. См. также раздел Объекты сопрограмм.
3.2.8.5. Асинхронные генераторные функции¶
Функция или метод, определённые с помощью async def и содержащие выражение yield, называются асинхронными генераторными функциями. При вызове такая функция возвращает объект асинхронного итератора, который можно использовать в инструкции async for для выполнения тела функции.
Вызов метода aiterator.__anext__ асинхронного итератора возвращает ожидаемый объект, который при ожидании выполняется до тех пор, пока не предоставит значение с помощью выражения yield. Когда функция выполняет пустую инструкцию return или доходит до конца, возникает исключение StopAsyncIteration, указывающее на исчерпание асинхронного итератора: он больше не выдаёт новых значений.
3.2.8.6. Встроенные функции¶
Объект встроенной функции является обёрткой вокруг C-функции. Примерами встроенных функций являются len() и math.sin() (math — стандартный встроенный модуль). Количество и тип аргументов определяются C-функцией. Специальные атрибуты, доступные только для чтения:
__doc__— строка документации функции илиNone, если она недоступна. См.function.__doc__.__name__— имя функции. См.function.__name__.__self__устанавливается вNone(но см. следующий пункт).__module__— имя модуля, в котором была определена функция, илиNone, если оно недоступно. См.function.__module__.
3.2.8.7. Встроенные методы¶
Это фактически другая форма встроенной функции, на этот раз содержащая объект, передаваемый C-функции в качестве неявного дополнительного аргумента. Пример встроенного метода — alist.append(), если alist является объектом списка. В этом случае специальный доступный только для чтения атрибут __self__ устанавливается в объект, обозначенный alist. (Атрибут имеет ту же семантику, что и в случае с другими методами экземпляра.)
3.2.8.8. Классы¶
Классы являются вызываемыми объектами. Обычно эти объекты служат фабриками для создания своих новых экземпляров, но для типов классов, переопределяющих __new__(), возможны варианты. Аргументы вызова передаются в __new__(), а в обычном случае — в __init__() для инициализации нового экземпляра.
3.2.8.9. Экземпляры классов¶
Экземпляры произвольных классов можно сделать вызываемыми, определив в их классе метод __call__().
3.2.9. Модули¶
Модули являются базовой организационной единицей кода Python и создаются системой импорта, вызываемой либо инструкцией import, либо вызовом функций, вроде importlib.import_module() или встроенной __import__(). Объект модуля имеет пространство имён, реализованное объектом словаря (это тот самый словарь, на который ссылается атрибут __globals__ функций, определённых в модуле). Обращения к атрибутам преобразуются в обращения к этому словарю; например, m.x эквивалентно m.__dict__["x"]. Объект модуля не содержит объект кода, использованный для инициализации модуля (поскольку после завершения инициализации он больше не нужен).
Присваивание атрибуту обновляет словарь пространства имён модуля, например, m.x = 1 эквивалентно m.__dict__["x"] = 1.
3.2.9.2. Другие доступные для записи атрибуты объектов модулей¶
Помимо перечисленных выше атрибутов, связанных с импортом, объекты модулей также имеют следующие доступные для записи атрибуты:
- module.__doc__¶
Строка документации модуля или
None, если она недоступна. См. также:__doc__ атрибуты.
- module.__annotations__¶
Словарь, содержащий аннотации переменных, собранные во время выполнения тела модуля. Рекомендации по работе с
__annotations__, см. вannotationlib.Изменено в версии 3.14: Теперь аннотации вычисляются лениво. См. PEP 649.
- module.__annotate__¶
Аннотирующая функция этого модуля или
None, если модуль не содержит аннотаций. См. также атрибуты__annotate__.Добавлено в версии 3.14.
- module.__lazy_modules__¶
Контейнер (объект, реализующий
__contains__()) строк с полными квалифицированными именами модулей. Если он определён на уровне модуля, любая обычная инструкцияimportв этом модуле, целевой модуль которой указан в этом контейнере, рассматривается как ленивый импорт, словно используется ключевое словоlazy. На импорты внутри функций, классов или блоковtry/except/finallyэто не влияет.Подробности и примеры см. в Совместимость через __lazy_modules__.
Добавлено в версии 3.15.
3.2.9.3. Словари модулей¶
Объекты модулей также имеют следующий специальный доступный только для чтения атрибут:
- module.__dict__¶
Пространство имён модуля в виде объекта-словаря. В отличие от всех остальных перечисленных здесь атрибутов,
__dict__нельзя получить как глобальную переменную внутри модуля. К нему можно обратиться только как к атрибуту объекта модуля.Из-за особенностей очистки словарей модулей в CPython словарь модуля будет очищен, когда модуль выйдет из области видимости, даже если на словарь по-прежнему существуют активные ссылки. Чтобы этого избежать, скопируйте словарь или сохраните модуль, пока напрямую используете его словарь.
3.2.10. Пользовательские классы¶
Типы пользовательских классов обычно создаются определениями классов (см. раздел Class definitions). У класса есть пространство имён, реализованное объектом-словарём. Обращения к атрибутам класса преобразуются в поиск в этом словаре: например, C.x преобразуется в C.__dict__["x"] (хотя существует ряд механизмов, позволяющих находить атрибуты другими способами). Если имя атрибута там не найдено, поиск атрибута продолжается в базовых классах. При поиске в базовых классах используется порядок разрешения методов C3, который корректно работает даже при «ромбовидном» наследовании, когда несколько путей наследования ведут к общему предку. Подробности об используемом Python порядке разрешения методов C3 можно найти в The Python 2.3 Method Resolution Order.
Если обращение к атрибуту класса (например, класса C) возвращает объект метода класса, он преобразуется в объект метода экземпляра, атрибут __self__ которого равен C. Если оно возвращает объект staticmethod, он преобразуется в объект, обёрнутый объектом статического метода. Другой способ, которым атрибуты, получаемые из класса, могут отличаться от атрибутов, непосредственно содержащихся в его __dict__, описан в разделе Реализация дескрипторов.
Присваивания атрибутам класса обновляют словарь класса, но никогда не словарь базового класса.
Объект класса можно вызвать (см. выше), чтобы получить экземпляр класса (см. ниже).
3.2.10.1. Специальные атрибуты¶
Атрибут |
Значение |
|---|---|
|
Имя класса. См. также: |
|
Квалифицированное имя класса. См. также: |
|
Имя модуля, в котором был определён класс. |
|
|
|
|
|
Единственный базовый класс в цепочке наследования, отвечающий за расположение экземпляров в памяти. Этот атрибут соответствует |
|
Строка документации класса или |
|
Словарь, содержащий аннотации переменных, собранные во время выполнения тела класса. См. также: Рекомендации по работе с Предупреждение Непосредственное обращение к атрибуту Этот атрибут отсутствует у некоторых встроенных классов. У пользовательских классов без Изменено в версии 3.14: Теперь аннотации вычисляются лениво. См. PEP 649. |
|
Аннотирующая функция для этого класса или Добавлено в версии 3.14. |
|
Добавлено в версии 3.12. |
|
Добавлено в версии 3.13. |
|
Номер строки, на которой начинается определение класса, включая декораторы. Присваивание атрибуту Добавлено в версии 3.13. |
|
|
3.2.10.2. Специальные методы¶
В дополнение к специальным атрибутам, описанным выше, все классы Python также имеют следующие два метода:
- type.mro()¶
Этот метод может быть переопределен метаклассом, чтобы настроить порядок разрешения методов для его экземпляров. Он вызывается при создании экземпляра класса, а его результат сохраняется в
__mro__.
- type.__subclasses__()¶
Каждый класс хранит список слабых ссылок на свои непосредственные подклассы. Этот метод возвращает список всех таких живых ссылок. Список приведён в порядке определения. Пример:
>>> class A: pass >>> class B(A): pass >>> A.__subclasses__() [<class 'B'>]
3.2.11. Экземпляры классов¶
Экземпляр класса создаётся вызовом объекта класса (см. выше). Экземпляр класса имеет пространство имён, реализованное в виде словаря, — именно в нём в первую очередь производится поиск обращений к атрибутам. Если атрибут там не найден, а класс экземпляра имеет атрибут с таким именем, поиск продолжается среди атрибутов класса. Если найденный атрибут класса является объектом пользовательской функции, он преобразуется в объект метода экземпляра, атрибут __self__ которого равен этому экземпляру. Объекты статических методов и методов класса также преобразуются — см. выше, в разделе «Классы». Другой способ, которым атрибуты класса, получаемые через его экземпляры, могут отличаться от объектов, фактически хранящихся в __dict__ класса, описан в разделе Реализация дескрипторов. Если атрибут класса не найден, а класс объекта имеет метод __getattr__(), он вызывается для удовлетворения запроса.
Присваивания атрибутов и их удаления обновляют словарь экземпляра, но никогда не обновляют словарь класса. Если у класса определён метод __setattr__() или __delattr__(), то он вызывается вместо непосредственного изменения словаря экземпляра.
Экземпляры классов могут вести себя как числа, последовательности или отображения, если в них определены методы с определёнными специальными именами. См. раздел Имена специальных методов.
3.2.11.1. Специальные атрибуты¶
- object.__class__¶
Класс, которому принадлежит экземпляр.
3.2.12. Объекты ввода-вывода (также известные как файловые объекты)¶
Файловый объект представляет собой открытый файл. Для создания файловых объектов доступны различные простые способы: встроенная функция open(), а также os.popen(), os.fdopen() и метод makefile() объектов сокетов (а возможно, и другие функции или методы, предоставляемые модулями расширений).
Файловые объекты реализуют общие методы, перечисленные ниже, чтобы упростить их использование в универсальном коде. Ожидается, что они являются Менеджеры контекста инструкции with.
Объекты sys.stdin, sys.stdout и sys.stderr инициализируются как файловые объекты, соответствующие стандартным потокам ввода, вывода и ошибок интерпретатора. Все они открыты в текстовом режиме и поэтому следуют интерфейсу, определённому абстрактным классом io.TextIOBase.
- file.read(size=-1, /)¶
Извлекает из файла до size данных. Для удобства, если size не указан или равен -1, извлекаются все доступные данные.
- file.write(data, /)¶
Сохраняет data в файл.
- file.close()¶
Сбрасывает все буферы и закрывает соответствующий файл.
3.2.13. Внутренние типы¶
Несколько типов, используемых интерпретатором внутри, доступны пользователю. Их определения могут измениться в будущих версиях интерпретатора, но они упомянуты здесь для полноты картины.
3.2.13.1. Объекты кода¶
Объекты кода представляют скомпилированный в байт-код исполняемый код Python, или байт-код. Отличие объекта кода от объекта функции в том, что объект функции содержит явную ссылку на глобальное пространство имён функции (модуль, в котором она была определена), тогда как объект кода не содержит никакого контекста. Кроме того, значения аргументов по умолчанию хранятся в объекте функции, а не в объекте кода (поскольку они представляют значения, вычисляемые во время выполнения). В отличие от объектов функций, объекты кода неизменяемы и не содержат ссылок (прямых или косвенных) на изменяемые объекты.
3.2.13.1.1. Специальные атрибуты, доступные только для чтения¶
|
Имя функции |
|
Полное квалифицированное имя функции Добавлено в версии 3.11. |
|
Общее количество позиционных параметров функции (включая только позиционные параметры и параметры со значениями по умолчанию) |
|
Количество только позиционных параметров функции (включая аргументы со значениями по умолчанию) |
|
Количество параметров функции, доступных только по имени (включая аргументы со значениями по умолчанию) |
|
Количество локальных переменных, используемых функцией (включая параметры) |
|
|
|
|
|
Примечание: ссылки на глобальные и встроенные имена не включены. |
|
Строка, представляющая последовательность инструкций байт-кода в функции |
|
|
|
|
|
Имя файла, из которого был скомпилирован код |
|
Номер первой строки функции |
|
Объект Добавлено в версии 3.10. |
|
Требуемый размер стека для объекта кода |
|
|
Для co_flags определены следующие биты флагов: бит 0x04 устанавливается, если функция использует синтаксис *arguments для приёма произвольного количества позиционных аргументов; бит 0x08 устанавливается, если функция использует синтаксис **keywords для приёма произвольных именованных аргументов; бит 0x20 устанавливается, если функция является генератором. Подробнее о семантике каждого из возможных флагов см. Code Objects Bit Flags.
Объявления будущих возможностей (например, from __future__ import division) также используют биты co_flags, чтобы указать, была ли включена определённая возможность при компиляции объекта кода. См. compiler_flag.
Другие биты co_flags зарезервированы для внутреннего использования.
Если объект кода представляет функцию и имеет строку документации, в co_flags устанавливается бит CO_HAS_DOCSTRING, а первым элементом co_consts становится строка документации функции.
3.2.13.1.2. Методы объектов кода¶
- codeobject.co_positions()¶
Возвращает итерируемый объект с позициями в исходном коде для каждой инструкции байт-кода в объекте кода.
Итератор возвращает
кортежи, содержащие(start_line, end_line, start_column, end_column). i-й кортеж соответствует позиции в исходном коде, скомпилированной в i-ю единицу кода. Информация о столбцах — это смещения в байтах UTF-8, отсчитываемые с 0, в пределах соответствующей строки исходного кода.Эта информация о позиции может отсутствовать. Неполный список случаев, когда это может произойти:
Запуск интерпретатора с параметром
-Xno_debug_ranges.Загрузка pyc-файла, скомпилированного с использованием
-Xno_debug_ranges.Кортежи позиций, соответствующие искусственным инструкциям.
Номера строк и столбцов, которые невозможно представить из-за ограничений конкретной реализации.
Когда это происходит, некоторые или все элементы кортежа могут быть равны
None.Добавлено в версии 3.11.
Примечание
Для этой функциональности требуется хранить позиции столбцов в объектах кода, что может привести к небольшому увеличению использования дискового пространства скомпилированными файлами Python или памяти, используемой интерпретатором. Чтобы избежать хранения этой дополнительной информации и/или отключить вывод дополнительной информации в трассировке, можно использовать флаг командной строки
-Xno_debug_rangesили переменную окруженияPYTHONNODEBUGRANGES.
- codeobject.co_lines()¶
Возвращает итератор, который выдаёт информацию о последовательных диапазонах байт-кода. Каждый выдаваемый элемент — это
tupleвида(start, end, lineno):start(int) представляет смещение (включительно) начала диапазона байт-кодаend(int) представляет смещение (не включая его) конца диапазона байт-кодаlineno— этоint, представляющий номер строки диапазона байт-кода, илиNone, если инструкции байт-кода в данном диапазоне не имеют номера строки
Выдаваемые элементы обладают следующими свойствами:
Первый выдаваемый диапазон будет иметь
start, равный 0.Диапазоны
(start, end)будут неубывающими и последовательными. То есть для любой парыкортежейзначениеstartвторого будет равно значениюendпервого.Ни один диапазон не будет направлен назад:
end >= startдля всех троек.Последний выдаваемый
tupleбудет иметьend, равный размеру байт-кода.
Допускаются диапазоны нулевой ширины, где
start == end. Они используются для строк, которые присутствуют в исходном коде, но были удалены компилятором байт-кода.Добавлено в версии 3.10.
См. также
- PEP 626 — Точные номера строк для отладки и других инструментов.
PEP, представивший метод
co_lines().
- codeobject.replace(**kwargs)¶
Возвращает копию объекта кода с новыми значениями для указанных полей.
Объекты кода также поддерживаются обобщённой функцией
copy.replace().Добавлено в версии 3.8.
3.2.13.2. Объекты кадров¶
Объекты кадров представляют исполняемые кадры. Они могут встречаться в объектах трассировки, а также передаются зарегистрированным функциям трассировки.
3.2.13.2.1. Специальные атрибуты, доступные только для чтения¶
|
Указывает на предыдущий кадр стека (в сторону вызывающего кода), или |
|
Объект кода, выполняемый в этом кадре. Обращение к этому атрибуту возбуждает событие аудита |
|
Отображение, используемое кадром для поиска локальных переменных. Если кадр относится к оптимизированной области видимости, этот метод может вернуть прокси-объект со сквозной записью. Изменено в версии 3.13: Возвращает прокси-объект для оптимизированных областей видимости. |
|
Словарь, используемый кадром для поиска глобальных переменных |
|
Словарь, используемый кадром для поиска встроенных (внутренних) имён |
|
«Точная инструкция» объекта кадра (это индекс в строке байт-кода объекта кода) |
|
Объект генератора или сопрограммы, которому принадлежит этот кадр, или Добавлено в версии 3.14. |
3.2.13.2.2. Специальные атрибуты, доступные для записи¶
|
Если не равно |
|
Установите этот атрибут в |
|
Установите этот атрибут в |
|
Текущий номер строки кадра — запись в этот атрибут из функции трассировки выполняет переход к указанной строке (только для самого нижнего кадра). Отладчик может реализовать команду перехода (также известную как «Установить следующую инструкцию»), записывая в этот атрибут. |
3.2.13.2.3. Методы объекта кадра¶
Объекты кадра поддерживают один метод:
- frame.clear()¶
Этот метод очищает все ссылки на локальные переменные, удерживаемые кадром. Также, если кадр принадлежал генератору, генератор финализируется. Это помогает разорвать циклы ссылок, включающие объекты кадра (например, при перехвате исключения и сохранении его трассировки для последующего использования).
Возбуждается
RuntimeError, если кадр в данный момент выполняется или приостановлен.Добавлено в версии 3.4.
Изменено в версии 3.13: Попытка очистить приостановленный кадр возбуждает
RuntimeError(как это всегда было и для выполняющихся кадров).
3.2.13.3. Объекты трассировки¶
Объекты трассировки представляют трассировку стека для исключения. Объект трассировки неявно создаётся при возникновении исключения, а также может быть явно создан вызовом types.TracebackType.
Изменено в версии 3.7: Объекты трассировки теперь можно явно создавать из кода Python.
Для неявно созданных трассировок, когда поиск обработчика исключения разворачивает стек выполнения, на каждом развёрнутом уровне перед текущей трассировкой вставляется объект трассировки. Когда управление передаётся обработчику исключения, трассировка стека становится доступна программе. (См. раздел The try statement.) Она доступна как третий элемент кортежа, возвращаемого функцией sys.exc_info(), а также как атрибут __traceback__ перехваченного исключения.
Если в программе нет подходящего обработчика, трассировка стека записывается (в аккуратно отформатированном виде) в стандартный поток ошибок. Если интерпретатор работает в интерактивном режиме, она также становится доступна пользователю как sys.last_traceback.
Для явно созданных трассировок ответственность за то, как атрибуты tb_next должны быть связаны для формирования полной трассировки стека, лежит на создателе трассировки.
Специальные атрибуты, доступные только для чтения:
|
Указывает на исполняемый кадр текущего уровня. Обращение к этому атрибуту возбуждает событие аудита |
|
Указывает номер строки, на которой возникло исключение |
|
Указывает на «точную инструкцию». |
Номер строки и последняя инструкция в трассировке могут отличаться от номера строки её объекта кадра, если исключение возникло в инструкции try без подходящей ветки except или с веткой finally.
- traceback.tb_next¶
Специальный доступный для записи атрибут
tb_next— это следующий уровень в трассировке стека (в сторону кадра, где возникло исключение), илиNone, если следующего уровня нет.Изменено в версии 3.7: Этот атрибут теперь доступен для записи
3.2.13.4. Объекты срезов¶
Объекты срезов используются для представления срезов в методах __getitem__(). Они также создаются встроенной функцией slice().
Добавлено в версии 3.15: Тип slice() теперь поддерживает обращение к элементу. Например, slice[float] можно использовать в аннотациях типов для указания среза, содержащего объекты float.
Специальные атрибуты, доступные только для чтения: start — нижняя граница; stop — верхняя граница; step — значение шага; каждый из них имеет значение None, если опущен. Эти атрибуты могут иметь любой тип.
Объекты среза поддерживают один метод:
- slice.indices(self, length)¶
Этот метод принимает единственный целочисленный аргумент length и вычисляет информацию о срезе, который описывал бы объект среза, если бы применялся к последовательности из length элементов. Он возвращает кортеж из трёх целых чисел; это, соответственно, индексы start и stop, а также step среза. Отсутствующие или выходящие за границы индексы обрабатываются так же, как и в обычных срезах.
3.2.13.5. Объекты статических методов¶
Объекты статических методов предоставляют способ обойти преобразование объектов функций в объекты методов, описанное выше. Объект статического метода — это обёртка вокруг любого другого объекта, обычно объекта пользовательского метода. Когда объект статического метода извлекается из класса или экземпляра класса, на самом деле возвращается обёрнутый объект, который не подвергается никаким дальнейшим преобразованиям. Объекты статических методов также являются вызываемыми. Объекты статических методов создаются встроенным конструктором staticmethod().
3.2.13.6. Объекты методов класса¶
Объект метода класса, как и объект статического метода, является обёрткой вокруг другого объекта, изменяющей то, как этот объект извлекается из классов и экземпляров классов. Поведение объектов методов класса при таком извлечении описано выше, в разделе «методы экземпляра». Объекты методов класса создаются встроенным конструктором classmethod().
3.3. Имена специальных методов¶
Класс может реализовывать определённые операции, вызываемые особым синтаксисом (такие как арифметические операции или обращение к элементу и срезы), определяя методы со специальными именами. Это подход Python к перегрузке операторов, позволяющий классам определять собственное поведение по отношению к операторам языка. Например, если класс определяет метод с именем __getitem__(), а x — экземпляр этого класса, то x[i] примерно эквивалентно type(x).__getitem__(x, i). За исключением специально оговорённых случаев, попытка выполнить операцию при отсутствии подходящего определённого метода возбуждает исключение (как правило, AttributeError или TypeError).
Установка специального метода в значение None означает, что соответствующая операция недоступна. Например, если класс устанавливает __iter__() в значение None, класс не является итерируемым, поэтому вызов iter() на его экземплярах будет возбуждать исключение TypeError (без отката к методу __getitem__()). [2]
При реализации класса, эмулирующего какой-либо встроенный тип, важно, чтобы эмуляция была реализована ровно в той мере, в какой это имеет смысл для моделируемого объекта. Например, некоторые последовательности могут хорошо работать с получением отдельных элементов, но извлечение среза может не иметь смысла. (Один из примеров этого — интерфейс NodeList в объектной модели документа W3C.)
3.3.1. Базовая настройка поведения¶
- object.__new__(cls[, ...])¶
Вызывается для создания нового экземпляра класса cls.
__new__()— это статический метод (особый случай, поэтому объявлять его как таковой явно не нужно), который принимает в качестве первого аргумента класс, экземпляр которого запрашивается. Остальные аргументы — это те, что были переданы выражению-конструктору объекта (вызову класса). Возвращаемым значением__new__()должен быть новый экземпляр объекта (обычно экземпляр cls).Типичные реализации создают новый экземпляр класса, вызывая метод
__new__()суперкласса с помощьюsuper().__new__(cls[, ...])с соответствующими аргументами, а затем при необходимости изменяют вновь созданный экземпляр перед тем, как вернуть его.Если
__new__()вызывается при создании объекта и возвращает экземпляр cls, то будет вызван метод__init__()нового экземпляра, как__init__(self[, ...]), где self — новый экземпляр, а остальные аргументы совпадают с теми, что были переданы конструктору объекта.Если
__new__()не возвращает экземпляр cls, то метод__init__()нового экземпляра вызван не будет.__new__()предназначен главным образом для того, чтобы позволить подклассам неизменяемых типов (таких как int, str или tuple) настраивать создание экземпляров. Его также часто переопределяют в пользовательских метаклассах, чтобы настроить создание классов.
- object.__init__(self[, ...])¶
Вызывается после того, как экземпляр был создан (методом
__new__()), но до того, как он возвращается вызывающему коду. Аргументы — это то, что было передано выражению-конструктору класса. Если у базового класса есть метод__init__(), метод__init__()производного класса, если он есть, должен явно вызвать его, чтобы обеспечить корректную инициализацию относящейся к базовому классу части экземпляра; например:super().__init__([args...]).Поскольку
__new__()и__init__()работают совместно при конструировании объектов (__new__()— чтобы создать объект, а__init__()— чтобы настроить его), метод__init__()не может возвращать никакое значение, кромеNone. В противном случае во время выполнения будет возбуждено исключениеTypeError.
- object.__del__(self)¶
Вызывается непосредственно перед уничтожением экземпляра. Такой метод также называют финализатором, или (не вполне точно) деструктором. Если у базового класса есть метод
__del__(), метод__del__()производного класса, если он есть, должен явно вызвать его, чтобы обеспечить корректное удаление относящейся к базовому классу части экземпляра.Метод
__del__()может (хотя это и не рекомендуется!) отложить уничтожение экземпляра, создав на него новую ссылку. Это называется воскрешением объекта. Будет ли__del__()вызван второй раз, когда воскрешённый объект снова соберутся уничтожить, зависит от реализации. Текущая реализация CPython вызывает его только один раз.Не гарантируется, что методы
__del__()будут вызваны для объектов, которые всё ещё существуют на момент завершения работы интерпретатора.weakref.finalizeпредоставляет простой способ зарегистрировать функцию очистки, которая будет вызвана, когда объект удаляется сборщиком мусора.Примечание
del xне вызываетx.__del__()напрямую — инструкция лишь уменьшает на единицу счётчик ссылок дляx, а метод вызывается только тогда, когда счётчик ссылок дляxдостигает нуля.Цикл ссылок может не дать счётчику ссылок объекта опуститься до нуля. В этом случае цикл будет позже обнаружен и удалён сборщиком циклического мусора. Частая причина циклов ссылок — исключение, перехваченное в локальной переменной. Тогда локальные переменные кадра ссылаются на исключение, которое ссылается на собственную трассировку, а та — на локальные переменные всех кадров, попавших в трассировку.
См. также
Документация модуля
gc.Предупреждение
Поскольку методы
__del__()вызываются в крайне неустойчивых условиях, исключения, возникающие при их выполнении, игнорируются, а вместо этого вsys.stderrвыводится предупреждение. В частности:__del__()может быть вызван во время выполнения произвольного кода, в том числе из любого потока. Если__del__()нужно захватить блокировку или обратиться к другому блокирующему ресурсу, возможна взаимная блокировка: ресурс может уже удерживаться кодом, который был прерван ради выполнения__del__()__del__()может выполняться во время завершения работы интерпретатора. Вследствие этого глобальные переменные, к которым он обращается (в том числе другие модули), могут быть уже удалены или установлены вNone. Python гарантирует, что глобальные переменные, имя которых начинается с одного символа подчёркивания, удаляются из своего модуля раньше остальных глобальных переменных. Если других ссылок на такие переменные нет, это может помочь обеспечить доступность импортированных модулей на момент вызова метода__del__().
- object.__repr__(self)¶
Вызывается встроенной функцией
repr()для вычисления «официального» строкового представления объекта. По возможности оно должно выглядеть как корректное выражение Python, с помощью которого можно воссоздать объект с тем же значением (при подходящем окружении). Если это невозможно, следует вернуть строку вида<...some useful description...>. Возвращаемое значение должно быть строковым объектом. Если класс определяет__repr__(), но не__str__(), то__repr__()также используется, когда требуется «неформальное» строковое представление экземпляров этого класса.Обычно это используется при отладке, поэтому важно, чтобы представление было информативным и однозначным. Реализация по умолчанию предоставляется самим классом
object.
- object.__str__(self)¶
Вызывается функцией
str(object), реализацией__format__()по умолчанию и встроенной функциейprint()для вычисления «неформального», или удобного для печати, строкового представления объекта. Возвращаемое значение должно быть объектом str.Этот метод отличается от
object.__repr__()тем, что от__str__()не требуется возвращать корректное выражение Python: можно использовать более удобное или краткое представление.Реализация по умолчанию, определённая во встроенном типе
object, вызываетobject.__repr__().
- object.__bytes__(self)¶
Вызывается функцией bytes для вычисления представления объекта в виде строки байтов. Метод должен возвращать объект
bytes. Сам классobjectэтот метод не предоставляет.
- object.__format__(self, format_spec)¶
Вызывается встроенной функцией
format()и, как следствие, при вычислении форматированных строковых литералов и методомstr.format()для получения «форматированного» строкового представления объекта. Аргумент format_spec — это строка, содержащая описание нужных параметров форматирования. Интерпретация аргумента format_spec зависит от типа, реализующего__format__(), однако большинство классов либо делегируют форматирование одному из встроенных типов, либо используют аналогичный синтаксис параметров форматирования.Описание стандартного синтаксиса форматирования см. в Format specification mini-language.
Возвращаемое значение должно быть строковым объектом.
Реализация по умолчанию в классе
objectдолжна получать пустую строку format_spec. Она делегирует вызов методу__str__().Изменено в версии 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.По умолчанию класс
objectпредоставляет реализации, согласованные с Value comparisons: равенство проверяется по идентичности объектов, а сравнения порядка возбуждаютTypeError. Каждый метод по умолчанию может выдавать эти результаты напрямую, но может также вернутьNotImplemented.См. абзац о
__hash__(), где приведены важные замечания о создании хешируемых объектов, которые поддерживают пользовательские операции сравнения и пригодны для использования в качестве ключей словаря.Версий этих методов с переставленными аргументами (которые использовались бы, когда левый аргумент не поддерживает операцию, а правый поддерживает) не существует. Вместо этого
__lt__()и__gt__()являются отражением друг друга,__le__()и__ge__()являются отражением друг друга, а__eq__()и__ne__()— каждый своим собственным отражением. Если операнды имеют разные типы, а тип правого операнда является прямым или косвенным подклассом типа левого операнда, приоритет имеет отражённый метод правого операнда, в противном случае приоритет имеет метод левого операнда. Виртуальные подклассы не учитываются.Если ни один из подходящих методов не возвращает значение, отличное от
NotImplemented, операторы==и!=переходят кisиis notсоответственно.
- object.__hash__(self)¶
Вызывается встроенной функцией
hash()и при операциях над элементами хеш-коллекций, включаяset,frozenset,dictиfrozendict. Метод__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__()(унаследованные от классаobject). С ними все объекты считаются неравными (кроме сравнения с самими собой), а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). Подробности см. на https://ocert.org/advisories/ocert-2011-003.html.
Изменение хеш-значений влияет на порядок итерации множеств. Python никогда не давал гарантий относительно этого порядка (и обычно он различается в 32-битных и 64-битных сборках).
См. также
PYTHONHASHSEED.Изменено в версии 3.3: Рандомизация хеширования теперь включена по умолчанию.
- object.__bool__(self)¶
Вызывается для реализации проверки истинности значения и встроенной операции
bool(). Метод должен возвращатьFalseилиTrue. Если этот метод не определён, вызывается__len__(), если он определён, и объект считается истинным, если результат ненулевой. Если класс не определяет ни__len__(), ни__bool__()(что верно и для самого классаobject), все его экземпляры считаются истинными.
3.3.2. Настройка доступа к атрибутам¶
Следующие методы можно определить, чтобы настроить поведение при доступе к атрибутам (получении значения, присваивании или удалении x.name) для экземпляров класса.
- object.__getattr__(self, name)¶
Вызывается, когда стандартный доступ к атрибуту завершается исключением
AttributeError. Это происходит, когда__getattribute__()возбуждаетAttributeError, потому что name не является ни атрибутом экземпляра, ни атрибутом в дереве классов объектаself, либо когда__get__()свойства name возбуждаетAttributeError. Метод должен либо вернуть (вычисленное) значение атрибута, либо возбудить исключениеAttributeError. Сам классobjectэтот метод не предоставляет.Обратите внимание: если атрибут найден обычным способом,
__getattr__()не вызывается. (Это намеренная асимметрия между__getattr__()и__setattr__().) Так сделано из соображений эффективности, а также потому, что иначе__getattr__()не смог бы обращаться к другим атрибутам экземпляра. Заметьте, что по крайней мере для переменных экземпляра полный контроль можно получить, если вообще не помещать значения в словарь атрибутов экземпляра, а хранить их в другом объекте. О том, как получить действительно полный контроль над доступом к атрибутам, см. описание метода__getattribute__()ниже.
- object.__getattribute__(self, name)¶
Вызывается безусловно при любом обращении к атрибутам экземпляров класса. Если в классе определён также метод
__getattr__(), он не будет вызван, если только__getattribute__()не вызовет его явно или не возбудитAttributeError. Метод должен вернуть (вычисленное) значение атрибута или возбудить исключениеAttributeError. Чтобы избежать бесконечной рекурсии, реализация этого метода должна всегда обращаться к нужным ей атрибутам через одноимённый метод базового класса, напримерobject.__getattribute__(self, name).Примечание
При поиске специальных методов, которые вызываются неявно через синтаксис языка или встроенные функции, этот метод всё равно может быть обойдён. См. Поиск специальных методов.
Для некоторых критичных обращений к атрибутам вызывает событие аудита
object.__getattr__с аргументамиobjиname.
- object.__setattr__(self, name, value)¶
Вызывается при попытке присвоить значение атрибуту. Этот метод вызывается вместо обычного механизма (то есть вместо сохранения значения в словаре экземпляра). name — имя атрибута, value — присваиваемое ему значение.
Чтобы присвоить значение атрибуту экземпляра, метод
__setattr__()должен вызвать одноимённый метод базового класса, напримерobject.__setattr__(self, name, value).Для некоторых критичных присваиваний атрибутов вызывает событие аудита
object.__setattr__с аргументамиobj,name,value.
- object.__delattr__(self, name)¶
Аналогичен методу
__setattr__(), но вызывается при удалении атрибута, а не при присваивании. Реализовывать его следует, только еслиdel obj.nameимеет смысл для данного объекта.Для некоторых критичных удалений атрибутов вызывает событие аудита
object.__delattr__с аргументамиobjиname.
- object.__dir__(self)¶
Вызывается, когда функция
dir()применяется к объекту. Метод должен возвращать итерируемый объект`. Функцияdir()преобразует возвращённый итерируемый объект в список и сортирует его.
3.3.2.1. Настройка доступа к атрибутам модуля¶
Специальные имена __getattr__ и __dir__ можно использовать и для настройки доступа к атрибутам модуля. Функция __getattr__ на уровне модуля должна принимать один аргумент, имя атрибута, и возвращать вычисленное значение или возбуждать AttributeError. Если атрибут не найден в объекте модуля обычным поиском, то есть через object.__getattribute__(), то перед возбуждением AttributeError функция __getattr__ ищется в __dict__ модуля. Если она найдена, то вызывается с именем атрибута, и её результат возвращается.
Функция __dir__ не должна принимать аргументов и должна возвращать итерируемый объект из строк с именами, доступными в модуле. Если такая функция есть, она заменяет стандартное поведение dir() для модуля.
- module.__class__¶
Для более тонкой настройки поведения модуля (установки атрибутов, свойств и т. д.) атрибуту __class__ объекта модуля можно присвоить подкласс types.ModuleType. Например:
import sys
from types import ModuleType
class VerboseModule(ModuleType):
def __repr__(self):
return f'Подробный {self.__name__}'
def __setattr__(self, attr, value):
print(f'Установка {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 ни один из этих протоколов не реализует.
- object.__get__(self, instance, owner=None)¶
Вызывается, чтобы получить атрибут класса владельца (доступ к атрибуту класса) или экземпляра этого класса (доступ к атрибуту экземпляра). Необязательный аргумент owner — это класс владельца, а instance — экземпляр, через который выполняется обращение к атрибуту, или
None, если обращение выполняется через owner.Этот метод должен возвращать вычисленное значение атрибута или возбуждать исключение
AttributeError.PEP 252 указывает, что
__get__()можно вызывать с одним или двумя аргументами. Встроенные дескрипторы Python поддерживают эту спецификацию. Однако вполне вероятно, что у некоторых сторонних инструментов есть дескрипторы, требующие оба аргумента. Собственная реализация__getattribute__()в Python всегда передаёт оба аргумента, независимо от того, требуются они или нет.
- object.__set__(self, instance, value)¶
Вызывается, чтобы присвоить атрибуту новое значение value в экземпляре instance класса владельца.
Обратите внимание: добавление
__set__()или__delete__()превращает дескриптор в «дескриптор данных». Подробнее см. в Вызов дескрипторов.
- object.__delete__(self, instance)¶
Вызывается, чтобы удалить атрибут в экземпляре instance класса владельца.
У экземпляров дескрипторов может быть также атрибут __objclass__:
- object.__objclass__¶
Атрибут
__objclass__интерпретируется модулемinspectкак указание на класс, в котором был определён этот объект (правильное значение этого атрибута помогает при интроспекции динамических атрибутов класса во время выполнения). Для вызываемых объектов он может означать, что экземпляр данного типа (или его подкласса) ожидается или требуется в качестве первого позиционного аргумента (например, CPython устанавливает этот атрибут для несвязанных методов, реализованных на C).
3.3.2.3. Вызов дескрипторов¶
В общем случае дескриптор — это атрибут объекта с «поведением привязки», то есть такой, доступ к которому переопределён методами протокола дескрипторов: __get__(), __set__() и __delete__(). Если для объекта определён любой из этих методов, он считается дескриптором.
Поведение по умолчанию при доступе к атрибуту — его получение, запись и удаление — работает со словарём объекта. Например, у a.x цепочка поиска начинается с a.__dict__['x'], затем идёт type(a).__dict__['x'] и далее по базовым классам type(a), не включая метаклассы.
Однако если найденное значение — объект, определяющий один из методов дескриптора, Python может переопределить поведение по умолчанию и вместо этого вызвать метод дескриптора. На каком месте в цепочке приоритетов это происходит, зависит от того, какие методы дескриптора определены и как они были вызваны.
Отправная точка вызова дескриптора — привязка a.x. То, как собираются аргументы, зависит от a:
- Прямой вызов
Самый простой и самый редкий вызов — когда пользовательский код напрямую вызывает метод дескриптора:
x.__get__(a).- Привязка к экземпляру
При привязке к экземпляру объекта
a.xпреобразуется в вызовtype(a).__dict__['x'].__get__(a, type(a)).- Привязка к классу
При привязке к классу
A.xпреобразуется в вызовA.__dict__['x'].__get__(None, A).- Привязка через super
Обращение через точку вида
super(A, a).xищет вa.__class__.__mro__базовый классB, следующий заA, и затем возвращаетB.__dict__['x'].__get__(a, A). Если это не дескриптор,xвозвращается без изменений.
При привязке к экземпляру приоритет вызова дескриптора зависит от того, какие методы дескриптора определены. Дескриптор может определять любое сочетание методов __get__(), __set__() и __delete__(). Если он не определяет __get__(), то при доступе к атрибуту будет возвращён сам объект дескриптора, если только в словаре экземпляра объекта не хранится значение. Если дескриптор определяет __set__(), либо __delete__(), либо оба этих метода, это дескриптор данных. Если не определяет ни того, ни другого, это дескриптор не-данных. Как правило, дескрипторы данных определяют и __get__(), и __set__(), тогда как у дескрипторов не-данных есть только метод __get__(). Дескрипторы данных, у которых определены __get__() и __set__() (и, возможно, __delete__()), всегда имеют приоритет над значением в словаре экземпляра. Напротив, дескрипторы не-данных могут быть переопределены экземплярами.
Методы Python (в том числе декорированные @staticmethod и @classmethod) реализованы как дескрипторы не-данных. Поэтому экземпляры могут переопределять методы. Это позволяет отдельным экземплярам приобретать поведение, отличное от поведения других экземпляров того же класса.
Декоратор @property реализован как дескриптор данных. Поэтому экземпляры не могут переопределять поведение свойства.
3.3.2.4. __slots__¶
__slots__ позволяют явно объявить атрибуты данных (наподобие свойств) и запретить создание __dict__ и __weakref__ (кроме случаев, когда они явно объявлены в __slots__ или уже есть в родительском классе).
Экономия места по сравнению с использованием __dict__ может быть значительной. Скорость поиска атрибутов тоже может заметно вырасти.
- object.__slots__¶
Этой переменной класса можно присвоить строку, итерируемый объект или последовательность строк с именами переменных, используемых экземплярами. __slots__ резервирует место для объявленных переменных и предотвращает автоматическое создание
__dict__и __weakref__ для каждого экземпляра.
Замечания по использованию __slots__:
При наследовании от класса без __slots__ атрибуты
__dict__и __weakref__ у экземпляров всегда будут доступны.Без переменной
__dict__экземплярам нельзя назначить новые переменные, не перечисленные в определении __slots__. Попытка присваивания переменной, не указанной в списке, выбрасываетAttributeError. Если требуется динамическое присваивание новых переменных, добавьте'__dict__'в последовательность строк в объявлении __slots__.Без переменной __weakref__ для каждого экземпляра классы, определяющие __slots__, не поддерживают
слабые ссылкина свои экземпляры. Если нужна поддержка слабых ссылок, добавьте'__weakref__'в последовательность строк в объявлении __slots__.__slots__ реализуются на уровне класса созданием дескрипторов для каждого имени переменной. Как следствие, атрибуты класса нельзя использовать для задания значений по умолчанию для переменных экземпляра, определённых в __slots__. Иначе атрибут класса перезаписал бы дескриптор.
Действие объявления __slots__ не ограничивается классом, в котором оно определено. __slots__, объявленные в родителях, доступны в дочерних классах. Однако экземпляры дочернего класса получат
__dict__и __weakref__, если только подкласс тоже не определяет __slots__ (который должен содержать лишь имена дополнительных слотов).Если класс определяет слот, который уже определён в базовом классе, то переменная экземпляра, определённая слотом базового класса, становится недоступной (кроме получения её дескриптора напрямую из базового класса). Это делает поведение программы неопределённым. В будущем может быть добавлена проверка, предотвращающая это.
Если для класса, производного от
встроенного типа «переменной длины», такого какint,bytesиtype, определены __slots__, кроме __dict__ и __weakref__, вызываетсяTypeError. Дляtupleэто правило не действует.Переменной __slots__ можно присвоить любой итерируемый объект, не являющийся строкой.
Если для задания __slots__ используется
словарь, его ключи становятся именами слотов. Значения словаря могут служить строками документации отдельных атрибутов. Такие строки распознаётinspect.getdoc(), и они отображаются в выводеhelp().Присваивание
__class__работает, только если у обоих классов одинаковые __slots__.Множественное наследование от нескольких родительских классов со слотами допускается, но только один родитель может иметь атрибуты, созданные слотами (остальные базовые классы должны иметь пустую структуру слотов). Нарушение этого правила вызывает
TypeError.Если для __slots__ используется итератор, то для каждого значения итератора создаётся дескриптор. Однако атрибут __slots__ при этом будет пустым итератором.
Изменено в версии 3.15: Разрешено определять __dict__ и __weakref__ в __slots__ для любого класса. Разрешено определять любые __slots__ для класса, производного от tuple.
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="Брюс"): pass
Реализация
object.__init_subclass__по умолчанию ничего не делает, но вызывает ошибку, если ей передать какие-либо именованные аргументы.Примечание
Подсказка метакласса
metaclassобрабатывается остальным механизмом типов и никогда не передаётся реализациям__init_subclass__. Фактический метакласс (а не явную подсказку) можно получить какtype(cls).Добавлено в версии 3.6.
Когда класс создаётся, type.__new__() просматривает переменные класса и вызывает метод __set_name__() у тех из них, где он определён.
- object.__set_name__(self, owner, name)¶
Автоматически вызывается в момент создания класса owner, которому принадлежит объект. Объект уже присвоен имени name в этом классе:
class A: x = C() # Автоматически вызывает: x.__set_name__(A, 'x')
Если переменная класса присваивается после создания класса,
__set_name__()не будет вызван автоматически. При необходимости__set_name__()можно вызвать напрямую:class A: pass c = C() A.x = c # Метод не вызывается c.__set_name__(A, 'x') # Вызываем метод вручную
Подробнее см. Создание объекта класса.
Добавлено в версии 3.6.
3.3.3.1. Метаклассы¶
По умолчанию классы создаются с помощью type(). Тело класса выполняется в новом пространстве имён, а имя класса локально привязывается к результату type(name, bases, namespace).
Процесс создания класса можно настроить, передав именованный аргумент metaclass в строке определения класса или наследуясь от существующего класса, в определении которого такой аргумент был указан. В следующем примере и MyClass, и MySubclass являются экземплярами Meta:
class Meta(type):
pass
class MyClass(metaclass=Meta):
pass
class MySubclass(MyClass):
pass
Все остальные именованные аргументы, указанные в определении класса, передаются во все описанные ниже операции метакласса.
При выполнении определения класса происходят следующие шаги:
разрешаются записи MRO;
определяется подходящий метакласс;
подготавливается пространство имён класса;
выполняется тело класса;
создаётся объект класса.
3.3.3.2. Разрешение записей MRO¶
- object.__mro_entries__(self, bases)¶
Если базовый класс, указанный в определении класса, не является экземпляром
type, то у него ищется метод__mro_entries__(). Если метод__mro_entries__()найден, то при создании класса базовый класс заменяется результатом вызова__mro_entries__(). Метод вызывается с исходным кортежем базовых классов, переданным в параметре bases, и должен возвращать кортеж классов, которые будут использованы вместо этого базового класса. Возвращаемый кортеж может быть пустым: в таком случае исходный базовый класс игнорируется.
См. также
types.resolve_bases()Динамически разрешает базовые классы, не являющиеся экземплярами
type.types.get_original_bases()Получает «исходные базовые классы» класса до изменений, внесённых методом
__mro_entries__().- PEP 560
Базовая поддержка модуля typing и обобщённых типов.
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 3.6 и новее ячейка __class__ передаётся метаклассу как запись __classcell__ в пространстве имён класса. Если она присутствует, её нужно передать дальше, в вызов type.__new__, чтобы класс был инициализирован правильно. Если этого не сделать, в Python 3.8 возникнет RuntimeError.
При использовании метакласса по умолчанию type или любого метакласса, который в итоге вызывает type.__new__, после создания объекта класса выполняются следующие дополнительные шаги настройки:
Метод
type.__new__собирает все атрибуты пространства имён класса, в которых определён метод__set_name__();Эти методы
__set_name__вызываются с создаваемым классом и присвоенным именем этого конкретного атрибута;Метод
__init_subclass__()вызывается у ближайшего родителя нового класса в его порядке разрешения методов.
После создания объекта класса он передаётся декораторам класса, указанным в определении класса (если они есть), а получившийся объект привязывается в локальном пространстве имён как определённый класс.
Когда новый класс создаётся методом type.__new__, объект, переданный в качестве параметра пространства имён, копируется в новое упорядоченное отображение, а исходный объект отбрасывается. Новая копия оборачивается в прокси только для чтения, который становится атрибутом __dict__ объекта класса.
См. также
- PEP 3135 — Новый super
Описывает неявную ссылку через замыкание
__class__
3.3.3.7. Применение метаклассов¶
Потенциальные области применения метаклассов безграничны. Среди идей, которые уже изучались, — перечисления, журналирование, проверка интерфейсов, автоматическое делегирование, автоматическое создание свойств, прокси, фреймворки, а также автоматическая блокировка и синхронизация ресурсов.
3.3.4. Настройка проверок экземпляров и подклассов¶
Следующие методы используются для переопределения поведения по умолчанию встроенных функций isinstance() и issubclass().
В частности, метакласс abc.ABCMeta реализует эти методы, чтобы позволить добавлять абстрактные базовые классы (ABC) в качестве «виртуальных базовых классов» к любому классу или типу (включая встроенные типы), в том числе к другим ABC.
- type.__instancecheck__(self, instance)¶
Возвращает истину, если instance следует считать (прямым или косвенным) экземпляром class. Если метод определён, он вызывается для реализации
isinstance(instance, class).
- type.__subclasscheck__(self, subclass)¶
Возвращает истину, если subclass следует считать (прямым или косвенным) подклассом class. Если метод определён, он вызывается для реализации
issubclass(subclass, class).
Обратите внимание, что эти методы ищутся в типе (метаклассе) класса. Их нельзя определить как методы класса в самом классе. Это согласуется с поиском специальных методов, вызываемых у экземпляров, с той разницей, что здесь сам экземпляр является классом.
См. также
- PEP 3119 — Введение абстрактных базовых классов
Содержит спецификацию настройки поведения
isinstance()иissubclass()с помощью__instancecheck__()и__subclasscheck__(), а также обоснование этой возможности в контексте добавления в язык абстрактных базовых классов (см. модульabc).
3.3.5. Эмуляция обобщённых типов¶
При использовании аннотаций типов часто удобно параметризовать обобщённый тип с помощью записи Python в квадратных скобках. Например, аннотация list[int] может обозначать list, все элементы которого имеют тип int.
См. также
- PEP 484 — Подсказки типов
Вводит в Python основу для аннотаций типов
- Типы обобщённых псевдонимов
Документация по объектам, представляющим собой параметризованные обобщённые классы
- Generics, пользовательские обобщённые типы и
typing.Generic Документация о том, как реализовать обобщённые классы, которые можно параметризовать во время выполнения и которые распознаются статическими системами проверки типов.
Класс обычно можно параметризовать, только если он определяет специальный метод класса __class_getitem__().
- classmethod object.__class_getitem__(cls, key)¶
Возвращает объект, представляющий специализацию обобщённого класса аргументами типа, найденными в key.
При определении в классе
__class_getitem__()автоматически становится методом класса. Поэтому декорировать его с помощью@classmethodне нужно.
3.3.5.1. Предназначение __class_getitem__¶
Предназначение __class_getitem__() — позволить параметризовать обобщённые классы стандартной библиотеки во время выполнения, чтобы было проще применять к ним подсказки типов.
Чтобы реализовать собственные обобщённые классы, которые можно параметризовать во время выполнения и которые распознаются статическими системами проверки типов, нужно наследоваться либо от класса стандартной библиотеки, уже реализующего __class_getitem__(), либо от typing.Generic, у которого есть собственная реализация __class_getitem__().
Собственные реализации __class_getitem__() в классах, определённых вне стандартной библиотеки, могут не распознаваться сторонними системами проверки типов, такими как mypy. Использовать __class_getitem__() в любых классах для целей, не связанных с подсказками типов, не рекомендуется.
3.3.5.2. __class_getitem__ против __getitem__¶
Обычно индексирование объекта с помощью квадратных скобок вызывает метод экземпляра __getitem__(), определённый в классе объекта. Однако вместо него может быть вызван метод класса __class_getitem__(), если сам индексируемый объект является классом. Правильно определённый __class_getitem__() должен возвращать объект GenericAlias.
Встретив выражение obj[x], интерпретатор Python решает, какой метод вызвать: __getitem__() или __class_getitem__() — примерно по такому алгоритму:
from inspect import isclass
def subscribe(obj, x):
"""Возвращает результат выражения 'obj[x]'"""
class_of_obj = type(obj)
# Если класс obj определяет __getitem__,
# вызываем class_of_obj.__getitem__(obj, x)
if hasattr(class_of_obj, '__getitem__'):
return class_of_obj.__getitem__(obj, x)
# Инча, если obj — класс и определяет __class_getitem__,
# вызываем obj.__class_getitem__(x)
elif isclass(obj) and hasattr(obj, '__class_getitem__'):
return obj.__class_getitem__(x)
# Иначе возбуждаем исключение
else:
raise TypeError(
f"'{class_of_obj.__name__}' object is not subscriptable"
)
В Python все классы сами являются экземплярами других классов. Класс класса называется метаклассом этого класса, и у большинства классов метаклассом является класс type. Класс type не определяет __getitem__(), поэтому выражения вида list[int], dict[str, float] и tuple[str, bytes] приводят к вызову __class_getitem__():
>>> # у list метаклассом, как и у большинства классов, является класс "type":
>>> type(list)
<class 'type'>
>>> type(dict) == type(list) == type(tuple) == type(str) == type(bytes)
True
>>> # "list[int]" вызывает "list.__class_getitem__(int)"
>>> list[int]
list[int]
>>> # list.__class_getitem__ возвращает объект GenericAlias:
>>> type(list[int])
<class 'types.GenericAlias'>
Однако если у класса есть собственный метакласс, определяющий __getitem__(), то обращение к классу по индексатору может вести себя иначе. Пример этого можно найти в модуле enum:
>>> from enum import Enum
>>> class Menu(Enum):
... """Меню завтрака"""
... SPAM = 'спам'
... BACON = 'бекон'
...
>>> # у классов Enum есть собственный метакласс:
>>> type(Menu)
<class 'enum.EnumMeta'>
>>> # EnumMeta определяет __getitem__,
>>> # поэтому __class_getitem__ не вызывается,
>>> # и результат не является объектом GenericAlias:
>>> Menu['SPAM']
<Menu.SPAM: 'спам'>
>>> type(Menu['SPAM'])
<enum 'Menu'>
См. также
- PEP 560 — Базовая поддержка модуля typing и обобщённых типов
Вводит
__class_getitem__()и описывает, когда обращение по индексатору приводит к вызову__class_getitem__()вместо__getitem__()
3.3.6. Эмуляция вызываемых объектов¶
3.3.7. Эмуляция контейнерных типов¶
Следующие методы можно определить, чтобы реализовать объекты-контейнеры. Сам класс object ни один из них не предоставляет. Обычно контейнеры — это последовательности (например, списки или кортежи) или отображения (например, словари), но могут быть и контейнеры других видов. Первая группа методов служит для эмуляции либо последовательности, либо отображения. Разница в том, что для последовательности допустимые ключи — это целые числа k, для которых 0 <= k < N, где N — длина последовательности, или объекты slice, задающие диапазон элементов. Также рекомендуется, чтобы отображения предоставляли методы keys(), values(), items(), get(), clear(), setdefault(), pop(), popitem(), copy() и update(), ведущие себя аналогично соответствующим методам стандартных объектов словарей Python. Модуль collections.abc предоставляет абстрактный базовый класс MutableMapping, который помогает создать эти методы на основе базового набора __getitem__(), __setitem__(), __delitem__() и keys().
Изменяемые последовательности должны предоставлять методы append(), clear(), count(), extend(), index(), insert(), pop(), remove() и reverse(), как стандартные объекты list Python. Наконец, типы последовательностей должны реализовывать сложение (то есть конкатенацию) и умножение (то есть повторение), определяя методы __add__(), __radd__(), __iadd__(), __mul__(), __rmul__() и __imul__(), описанные ниже. Другие числовые операторы им определять не следует.
Рекомендуется, чтобы и отображения, и последовательности реализовывали метод __contains__(). Это позволит эффективно использовать оператор in. Для отображений in должен искать среди ключей, для последовательностей — среди значений. Кроме того, рекомендуется, чтобы и отображения, и последовательности реализовывали метод __iter__(). Это позволит эффективно перебирать элементы контейнера. Для отображений __iter__() должен перебирать ключи объекта, для последовательностей — значения.
- object.__len__(self)¶
Вызывается для реализации встроенной функции
len(). Должен возвращать длину объекта — целое число>=0. Кроме того, объект, у которого не определён метод__bool__(), а метод__len__()возвращает ноль, считается ложным в логическом контексте.В CPython длина не может превышать
sys.maxsize. Если длина большеsys.maxsize, некоторые функции (например,len()) могут вызыватьOverflowError. Чтобы проверка истинности не вызывалаOverflowError, объект должен определять метод__bool__().
- object.__length_hint__(self)¶
Вызывается для реализации
operator.length_hint(). Должен возвращать приблизительную длину объекта (она может быть как больше, так и меньше фактической). Длина должна быть целым числом>=0. Возвращаемое значение может также бытьNotImplemented. Тогда это воспринимается так, как будто метода__length_hint__не существует вовсе. Этот метод — лишь оптимизация, и для корректности он никогда не требуется.Добавлено в версии 3.4.
- object.__getitem__(self, subscript)¶
Вызывается для реализации индексирования, то есть
self[subscript]. Подробности о синтаксисе см. в Subscriptions and slicings.Есть два типа встроенных объектов, которые поддерживают индексирование через
__getitem__():последовательности, где индексатор (его также называют индексом) должен быть целым числом или объектом
slice. Ожидаемое поведение, включая обработку объектовsliceи отрицательных индексов, описано в документации по последовательностям.отображения, где индексатор также называют ключом. Ожидаемое поведение описано в документации по отображениям.
Если индексатор имеет неподходящий тип,
__getitem__()должен вызыватьTypeError. Если индексатор имеет неподходящее значение,__getitem__()должен вызыватьLookupErrorили один из его подклассов (IndexErrorдля последовательностей,KeyErrorдля отображений).Примечание
Срезы обрабатываются методами
__getitem__(),__setitem__()и__delitem__(). Вызов видаa[1:2] = b
преобразуется в
a[slice(1, 2, None)] = b
и так далее. Пропущенные элементы среза всегда заполняются значением
None.Примечание
Протокол итерации последовательностей (он используется, например, в циклах
for) ожидает, что для недопустимых индексов будет вызванIndexError. Это позволяет правильно определить конец последовательности.Примечание
При индексировании класса вместо
__getitem__()может быть вызван специальный метод класса__class_getitem__(). Подробности см. в __class_getitem__ против __getitem__.
- object.__setitem__(self, key, value)¶
Вызывается для реализации присваивания
self[key]. Действует то же замечание, что и для__getitem__(). Для отображений метод следует реализовывать, только если объекты поддерживают изменение значений по ключам или добавление новых ключей, а для последовательностей — только если элементы можно заменять. Для недопустимых значений key должны вызываться те же исключения, что и в методе__getitem__().
- object.__delitem__(self, key)¶
Вызывается для реализации удаления
self[key]. Действует то же замечание, что и для__getitem__(). Для отображений метод следует реализовывать, только если объекты поддерживают удаление ключей, а для последовательностей — только если элементы можно удалять из последовательности. Для недопустимых значений key должны вызываться те же исключения, что и в методе__getitem__().
- object.__missing__(self, key)¶
Вызывается методом
dict.__getitem__()для реализацииself[key]в подклассах dict, когда ключ отсутствует в словаре.
- object.__iter__(self)¶
Этот метод вызывается, когда для контейнера требуется итератор. Он должен возвращать новый объект-итератор, который может перебирать все объекты в контейнере. Для отображений он должен перебирать ключи контейнера.
- object.__reversed__(self)¶
Вызывается (если присутствует) встроенной функцией
reversed()для реализации обратной итерации. Должен возвращать новый объект-итератор, который перебирает все объекты в контейнере в обратном порядке.Если метод
__reversed__()не предоставлен, встроенная функцияreversed()вместо него использует протокол последовательности (__len__()и__getitem__()). Объекты, поддерживающие протокол последовательности, должны предоставлять__reversed__()только в том случае, если могут предложить реализацию эффективнее той, которую предоставляетreversed().
Операторы проверки принадлежности (in и not in) обычно реализуются как итерация по контейнеру. Однако объекты-контейнеры могут предоставить следующий специальный метод с более эффективной реализацией, которая к тому же не требует, чтобы объект был итерируемым.
- object.__contains__(self, item)¶
Вызывается для реализации операторов проверки принадлежности. Должен возвращать истину, если item есть в self, и ложь в противном случае. Для объектов-отображений метод должен учитывать ключи отображения, а не значения или пары «ключ — значение».
Для объектов, у которых метод
__contains__()не определён, проверка принадлежности сначала пытается перебрать элементы через__iter__(), затем использует старый протокол итерации последовательностей через__getitem__(). См. этот раздел справочника по языку.
3.3.8. Эмуляция числовых типов¶
Следующие методы можно определить, чтобы эмулировать числовые объекты. Методы, соответствующие операциям, которые не поддерживаются конкретным видом реализуемого числа (например, побитовые операции для нецелых чисел), следует оставить неопределёнными.
- object.__add__(self, other)¶
- object.__sub__(self, other)¶
- object.__mul__(self, other)¶
- object.__matmul__(self, other)¶
- object.__truediv__(self, other)¶
- object.__floordiv__(self, other)¶
- object.__mod__(self, other)¶
- object.__divmod__(self, other)¶
- object.__pow__(self, other[, modulo])¶
- object.__lshift__(self, other)¶
- object.__rshift__(self, other)¶
- object.__and__(self, other)¶
- object.__xor__(self, other)¶
- object.__or__(self, other)¶
Эти методы вызываются для реализации бинарных арифметических операций (
+,-,*,@,/,//,%,divmod(),pow(),**,<<,>>,&,^,|). Например, чтобы вычислить выражениеx + y, где x — экземпляр класса с методом__add__(), вызываетсяtype(x).__add__(x, y). Метод__divmod__()должен быть эквивалентен использованию__floordiv__()и__mod__(). Он не должен быть связан с__truediv__(). Обратите внимание, что метод__pow__()должен принимать необязательный третий аргумент, если требуется поддержка трёхаргументной версии встроенной функцииpow().Если один из этих методов не поддерживает операцию с переданными аргументами, он должен возвращать
NotImplemented.
- object.__radd__(self, other)¶
- object.__rsub__(self, other)¶
- object.__rmul__(self, other)¶
- object.__rmatmul__(self, other)¶
- object.__rtruediv__(self, other)¶
- object.__rfloordiv__(self, other)¶
- object.__rmod__(self, other)¶
- object.__rdivmod__(self, other)¶
- object.__rpow__(self, other[, modulo])¶
- object.__rlshift__(self, other)¶
- object.__rrshift__(self, other)¶
- object.__rand__(self, other)¶
- object.__rxor__(self, other)¶
- object.__ror__(self, other)¶
Эти методы вызываются для реализации бинарных арифметических операций (
+,-,*,@,/,//,%,divmod(),pow(),**,<<,>>,&,^,|) с отражёнными (переставленными) операндами. Эти методы вызываются, только если операнды имеют разные типы и при этом либо левый операнд не поддерживает соответствующую операцию [3], либо класс правого операнда является производным от класса левого операнда. [4] Например, чтобы вычислить выражениеx - y, где y — экземпляр класса с методом__rsub__(), вызываетсяtype(y).__rsub__(y, x), еслиtype(x).__sub__(x, y)возвращаетNotImplementedилиtype(y)является подклассомtype(x). [5]Обратите внимание, что метод
__rpow__()должен принимать необязательный третий аргумент, если требуется поддержка трёхаргументной версии встроенной функцииpow().Изменено в версии 3.14: Трёхаргументная функция
pow()теперь при необходимости пытается вызвать__rpow__(). Раньше этот метод вызывался только в двухаргументнойpow()и в бинарном операторе возведения в степень.Примечание
Если тип правого операнда является подклассом типа левого операнда и этот подкласс предоставляет другую реализацию отражённого метода для данной операции, то этот метод будет вызван раньше неотражённого метода левого операнда. Такое поведение позволяет подклассам переопределять операции своих предков.
- object.__iadd__(self, other)¶
- object.__isub__(self, other)¶
- object.__imul__(self, other)¶
- object.__imatmul__(self, other)¶
- object.__itruediv__(self, other)¶
- object.__ifloordiv__(self, other)¶
- object.__imod__(self, other)¶
- object.__ipow__(self, other[, modulo])¶
- object.__ilshift__(self, other)¶
- object.__irshift__(self, other)¶
- object.__iand__(self, other)¶
- object.__ixor__(self, other)¶
- object.__ior__(self, other)¶
Эти методы вызываются для реализации комбинированных арифметических присваиваний (
+=,-=,*=,@=,/=,//=,%=,**=,<<=,>>=,&=,^=,|=). Они должны пытаться выполнить операцию на месте (изменяя self) и возвращать результат (это может быть, но не обязательно, self). Если конкретный метод не определён или возвращаетNotImplemented, комбинированное присваивание переходит к обычным методам. Например, если x — экземпляр класса с методом__iadd__(), тоx += yэквивалентноx = x.__iadd__(y). Если__iadd__()не существует илиx.__iadd__(y)возвращаетNotImplemented, то, как и при вычисленииx + y, рассматриваютсяx.__add__(y)иy.__radd__(x). В некоторых ситуациях комбинированное присваивание может приводить к неожиданным ошибкам (см. Why does a_tuple[i] += [„item“] raise an exception when the addition works?), но такое поведение на самом деле является частью модели данных.
- 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()и функцийtrunc(),floor()иceil()модуляmath. Если в__round__()не передан ndigits, все эти методы должны возвращать значение объекта, усечённое доIntegral(как правило,int).Изменено в версии 3.14: Функция
int()больше не делегирует вызов методу__trunc__().
3.3.9. Менеджеры контекста инструкции with¶
Менеджер контекста — это объект, определяющий контекст времени выполнения, который устанавливается при выполнении инструкции with. Менеджер контекста отвечает за вход в контекст времени выполнения, необходимый для выполнения блока кода, и за выход из этого контекста. Обычно менеджеры контекста вызываются с помощью инструкции with (описанной в разделе The with statement), но их можно использовать и напрямую, вызывая их методы.
Типичные примеры применения менеджеров контекста: сохранение и восстановление различных видов глобального состояния, блокировка и разблокировка ресурсов, закрытие открытых файлов и т. д.
Дополнительные сведения о менеджерах контекста см. в Context Manager Types. Сам класс object методов менеджера контекста не предоставляет.
- object.__enter__(self)¶
Входит в контекст времени выполнения, связанный с этим объектом. Инструкция
withпривязывает возвращаемое значение этого метода к цели или целям, указанным в конструкцииasинструкции (если она есть).
- object.__exit__(self, exc_type, exc_value, traceback)¶
Выходит из контекста времени выполнения, связанного с этим объектом. Параметры описывают исключение, из-за которого произошёл выход из контекста. Если выход из контекста произошёл без исключения, все три аргумента равны
None.Если передано исключение и метод хочет его подавить (то есть не дать ему распространяться дальше), он должен вернуть истинное значение. В противном случае исключение будет обработано как обычно после выхода из этого метода.
Обратите внимание, что методы
__exit__()не должны повторно возбуждать переданное исключение. Это ответственность вызывающего кода.
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 — Структурное сопоставление с шаблоном
Спецификация инструкции
matchязыка Python.
3.3.11. Эмуляция буферных типов¶
Протокол буфера позволяет объектам Python предоставлять эффективный доступ к низкоуровневому массиву памяти. Этот протокол реализован во встроенных типах, таких как bytes и memoryview, а сторонние библиотеки могут определять дополнительные буферные типы.
Хотя буферные типы обычно реализуются на C, протокол можно реализовать и на Python.
- object.__buffer__(self, flags)¶
Вызывается, когда у self запрашивается буфер (например, конструктором
memoryview). Аргумент flags — целое число, определяющее вид запрашиваемого буфера: например, будет ли возвращаемый буфер доступен только для чтения или для записи. Удобный способ интерпретировать флаги предоставляетinspect.BufferFlags. Метод должен возвращать объектmemoryview.Потокобезопасность: В Python со свободной многопоточностью реализации должны управлять любым внутренним счётчиком экспорта с помощью атомарных операций. Метод должен безопасно вызываться конкурентно из нескольких потоков, а данные, лежащие в основе возвращаемого буфера, должны оставаться действительными, пока не завершится соответствующий вызов
__release_buffer__(). Подробности см. в Thread safety for memoryview objects.
- object.__release_buffer__(self, buffer)¶
Вызывается, когда буфер больше не нужен. Аргумент buffer — объект
memoryview, ранее возвращённый методом__buffer__(). Метод должен освободить все ресурсы, связанные с буфером. Этот метод должен возвращатьNone.Потокобезопасность: В Python со свободной многопоточностью любое уменьшение счётчика экспорта должно использовать атомарные операции. Освобождение ресурсов должно быть потокобезопасным, так как последнее освобождение может оказаться в гонке с конкурентными освобождениями из других потоков.
Буферным объектам, которым не нужно выполнять никакой очистки, реализовывать этот метод необязательно.
Добавлено в версии 3.12.
См. также
- PEP 688 — Обеспечение доступа к протоколу буфера из Python
Представляет методы Python
__buffer__и__release_buffer__.collections.abc.BufferАбстрактный базовый класс для буферных типов.
3.3.12. Аннотации¶
Функции, классы и модули могут содержать аннотации — способ связать информацию (обычно подсказки типов) с символом.
- object.__annotations__¶
Этот атрибут содержит аннотации объекта. Он вычисляется лениво, поэтому обращение к атрибуту может выполнить произвольный код и вызвать исключения. Если вычисление прошло успешно, в атрибут записывается словарь, сопоставляющий имена переменных с аннотациями.
Изменено в версии 3.14: Аннотации теперь вычисляются лениво.
- object.__annotate__(format)¶
Аннотирующая функция. Возвращает новый словарь, сопоставляющий имена атрибутов или параметров с их значениями аннотаций.
Принимает параметр, задающий формат, в котором должны предоставляться значения аннотаций. Он должен быть членом перечисления
annotationlib.Formatили целым числом, значение которого соответствует члену перечисления.Если аннотирующая функция не поддерживает запрошенный формат, она должна возбудить
NotImplementedError. Аннотирующие функции обязаны всегда поддерживать форматVALUE: при вызове с этим форматом они не должны возбуждатьNotImplementedError().При вызове с форматом
VALUEаннотирующая функция может возбудитьNameError. При запросе любого другого формата она не должна возбуждатьNameError.Если у объекта нет аннотаций, его атрибуту
__annotate__лучше присвоить значениеNoneвместо функции, возвращающей пустой словарь. Удалить этот атрибут нельзя.Добавлено в версии 3.14.
См. также
- PEP 649 — Отложенное вычисление аннотаций с помощью дескрипторов
Представляет ленивое вычисление аннотаций и функцию
__annotate__.
3.3.13. Поиск специальных методов¶
Для пользовательских классов неявные вызовы специальных методов гарантированно работают правильно, только если они определены в типе объекта, а не в словаре экземпляра объекта. Именно поэтому следующий код возбуждает исключение:
>>> class C:
... pass
...
>>> c = C()
>>> c.__len__ = lambda: 5
>>> len(c)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type 'C' has no len()
Причина такого поведения кроется в ряде специальных методов, таких как __hash__() и __repr__(), которые реализованы у всех объектов, включая объекты типов. Если бы неявный поиск этих методов шёл обычным образом, их вызов для самого объекта типа завершался бы ошибкой:
>>> 1 .__hash__() == hash(1)
True
>>> int.__hash__() == hash(int)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: descriptor '__hash__' of 'int' object needs an argument
Такая ошибочная попытка вызвать несвязанный метод класса иногда называется «путаницей метаклассов». Чтобы её избежать, при поиске специальных методов экземпляр обходится:
>>> type(1).__hash__(1) == hash(1)
True
>>> type(int).__hash__(int) == hash(int)
True
Помимо обхода любых атрибутов экземпляра ради корректности, неявный поиск специальных методов, как правило, обходит и метод __getattribute__(), даже у метакласса объекта:
>>> class Meta(type):
... def __getattribute__(*args):
... print("Вызван getattribute метакласса")
... return type.__getattribute__(*args)
...
>>> class C(object, metaclass=Meta):
... def __len__(self):
... return 10
... def __getattribute__(*args):
... print("Вызван getattribute класса")
... return object.__getattribute__(*args)
...
>>> c = C()
>>> c.__len__() # Явный поиск через экземпляр
Class getattribute invoked
10
>>> type(c).__len__(c) # Явный поиск через тип
Metaclass getattribute invoked
10
>>> len(c) # Неявный поиск
10
Такой обход механизма __getattribute__() даёт широкие возможности для оптимизации скорости внутри интерпретатора. Платой за это становится некоторая потеря гибкости при работе со специальными методами: чтобы интерпретатор последовательно вызывал специальный метод, он обязательно должен быть задан в самом объекте класса.
3.4. Сопрограммы¶
3.4.1. Ожидаемые объекты¶
Ожидаемый объект обычно реализует метод __await__(). Объекты сопрограмм, возвращаемые функциями async def, являются ожидаемыми объектами.
Примечание
Объекты генераторных итераторов, возвращаемые генераторами, декорированными с помощью types.coroutine(), тоже являются ожидаемыми, но не реализуют __await__().
- object.__await__(self)¶
Должен возвращать итератор. Предназначен для реализации ожидаемых объектов. Например,
asyncio.Futureреализует этот метод, чтобы быть совместимым с выражениемawait. Сам классobjectне является ожидаемым объектом и этот метод не предоставляет.Примечание
Язык не накладывает никаких ограничений на тип или значение объектов, выдаваемых итератором, который возвращает
__await__: это зависит от реализации фреймворка асинхронного выполнения (например,asyncio), который управляет ожидаемым объектом.
Добавлено в версии 3.5.
См. также
Дополнительную информацию об ожидаемых объектах см. в PEP 492.
3.4.2. Объекты сопрограмм¶
Объекты сопрограмм являются ожидаемыми объектами. Выполнением сопрограммы можно управлять, вызывая __await__() и перебирая результат. Когда сопрограмма завершает выполнение и возвращает значение, итератор возбуждает StopIteration, а атрибут value этого исключения хранит возвращаемое значение. Если сопрограмма возбуждает исключение, итератор передаёт его дальше. Сопрограммы не должны напрямую возбуждать необработанные исключения StopIteration.
У сопрограмм также есть перечисленные ниже методы, аналогичные методам генераторов (см. Generator-iterator methods). Однако, в отличие от генераторов, сопрограммы не поддерживают итерацию напрямую.
Сопрограммы являются обобщёнными по типам выдаваемых, принимаемых и возвращаемых ими значений соответственно.
Изменено в версии 3.5.2: Повторное ожидание сопрограммы возбуждает RuntimeError.
- coroutine.send(value)¶
Запускает или возобновляет выполнение сопрограммы. Если value равно
None, это эквивалентно продвижению итератора, возвращённого__await__(). Если value не равноNone, этот метод делегирует вызов методуsend()итератора, из-за которого сопрограмма приостановилась. Результат (возвращаемое значение,StopIterationили другое исключение) тот же, что и при переборе значения, возвращаемого__await__(), как описано выше.
- coroutine.throw(value)¶
- coroutine.throw(type[, value[, traceback]])
Возбуждает указанное исключение в сопрограмме. Этот метод делегирует вызов методу
throw()итератора, из-за которого сопрограмма приостановилась, если у того есть такой метод. В противном случае исключение возбуждается в точке приостановки. Результат (возвращаемое значение,StopIterationили другое исключение) тот же, что и при переборе значения, возвращаемого__await__(), как описано выше. Если исключение не перехвачено в сопрограмме, оно распространяется обратно к вызывающему.Изменено в версии 3.12: Вторая сигнатура (type[, value[, traceback]]) устарела и может быть удалена в будущей версии Python.
- coroutine.close()¶
Заставляет сопрограмму выполнить очистку и завершиться. Если сопрограмма приостановлена, этот метод сначала делегирует вызов методу
close()итератора, из-за которого сопрограмма приостановилась, если у того есть такой метод. Затем он возбуждаетGeneratorExitв точке приостановки, из-за чего сопрограмма немедленно выполняет очистку. Наконец, сопрограмма помечается как завершившая выполнение, даже если она никогда не запускалась.Перед уничтожением объекты сопрограмм автоматически закрываются описанным выше способом.
3.4.3. Асинхронные итераторы¶
Асинхронный итератор может вызывать асинхронный код в своём методе __anext__.
Асинхронные итераторы можно использовать в инструкции async for.
Сам класс object этих методов не предоставляет.
- object.__aiter__(self)¶
Должен возвращать объект асинхронного итератора.
- object.__anext__(self)¶
Должен возвращать ожидаемый объект, результатом которого является следующее значение итератора. Когда итерация закончена, должен возбуждать исключение
StopAsyncIteration.
Пример асинхронного итерируемого объекта:
class Reader:
async def readline(self):
...
def __aiter__(self):
return self
async def __anext__(self):
val = await self.readline()
if val == b'':
raise StopAsyncIteration
return val
Добавлено в версии 3.5.
Изменено в версии 3.7: До Python 3.7 метод __aiter__() мог возвращать ожидаемый объект, который разрешался в асинхронный итератор.
Начиная с Python 3.7 метод __aiter__() должен возвращать объект асинхронного итератора. Возврат любого другого значения приведёт к ошибке TypeError.
3.4.4. Асинхронные менеджеры контекста¶
Асинхронный менеджер контекста — это менеджер контекста, который может приостанавливать выполнение в своих методах __aenter__ и __aexit__.
Асинхронные менеджеры контекста можно использовать в инструкции async with.
Сам класс object этих методов не предоставляет.
- object.__aenter__(self)¶
Семантически похож на
__enter__(), с той лишь разницей, что должен возвращать ожидаемый объект.
- object.__aexit__(self, exc_type, exc_value, traceback)¶
Семантически похож на
__exit__(), с той лишь разницей, что должен возвращать ожидаемый объект.
Пример класса асинхронного менеджера контекста:
class AsyncContextManager:
async def __aenter__(self):
await log('вход в контекст')
async def __aexit__(self, exc_type, exc, tb):
await log('выход из контекста')
Добавлено в версии 3.5.
Примечания