3. Модель данных¶
3.1. Объекты, значения и типы¶
Objects - это абстракция данных в Python. Все данные в программе на Python представлены объектами или отношениями между объектами. (В некотором смысле, в соответствии с моделью Фон Неймана о «компьютере с хранимой программой», код также представлен объектами.)
У каждого объекта есть идентификатор, тип и значение. Идентификатор объекта никогда не меняется после его создания; вы можете рассматривать его как адрес объекта в памяти. Оператор is
сравнивает идентичность двух объектов; функция id()
возвращает целое число, представляющее его идентичность.
Детали реализации CPython: Для CPython id(x)
- это адрес памяти, в которой хранится x
.
Тип объекта определяет операции, которые поддерживает объект (например, «имеет ли он длину?»), а также определяет возможные значения для объектов этого типа. Функция type()
возвращает тип объекта (который сам по себе является объектом). Как и его идентичность, type объекта также является неизменяемым. [1]
Значение некоторых объектов может изменяться. Объекты, значение которых может изменяться, называются изменяемыми; объекты, значение которых остается неизменным после их создания, называются неизменяемыми. (Значение неизменяемого объекта-контейнера, содержащего ссылку на изменяемый объект, может изменяться при изменении значения последнего; однако контейнер по-прежнему считается неизменяемым, поскольку содержащаяся в нем коллекция объектов не может быть изменена. Таким образом, неизменяемость - это не совсем то же самое, что наличие неизменяемого значения, это более тонкий подход.) Изменчивость объекта определяется его типом; например, числа, строки и кортежи неизменяемы, в то время как словари и списки изменяемы.
Объекты никогда не уничтожаются явно; однако, когда они становятся недоступными, они могут быть отправлены в мусорную корзину. Реализации разрешается отложить сборку мусора или вообще отказаться от нее - то, как выполняется сборка мусора, зависит от качества реализации, до тех пор, пока не будут собраны объекты, которые все еще доступны.
Детали реализации CPython: В настоящее время CPython использует схему подсчета ссылок с (необязательным) отложенным обнаружением циклически связанного мусора, которая собирает большинство объектов, как только они становятся недоступными, но не гарантирует сбор мусора, содержащего циклические ссылки. Смотрите документацию к модулю gc
для получения информации об управлении сбором циклического мусора. Другие реализации работают по-другому, и CPython может измениться. Не зависит от немедленного завершения объектов, когда они становятся недоступными (поэтому вы всегда должны явно закрывать файлы).
Обратите внимание, что использование средств трассировки или отладки реализации может поддерживать работоспособность объектов, которые обычно доступны для сбора. Также обратите внимание, что перехват исключения с помощью инструкции try
…except
может поддерживать работоспособность объектов.
Некоторые объекты содержат ссылки на «внешние» ресурсы, такие как открытые файлы или Windows. Понятно, что эти ресурсы освобождаются при сборке мусора для объекта, но поскольку сбор мусора не гарантирован, такие объекты также предоставляют явный способ освобождения внешнего ресурса, обычно это метод close()
. Программам настоятельно рекомендуется явно закрывать такие объекты. Инструкция try
…finally
и инструкция with
предоставляют удобные способы сделать это.
Некоторые объекты содержат ссылки на другие объекты; они называются контейнерами. Примерами контейнеров являются кортежи, списки и словари. Ссылки являются частью значения контейнера. В большинстве случаев, когда мы говорим о значении контейнера, мы подразумеваем значения, а не идентификаторы содержащихся в нем объектов; однако, когда мы говорим об изменчивости контейнера, подразумеваются только идентификаторы непосредственно содержащихся в нем объектов. Таким образом, если неизменяемый контейнер (например, кортеж) содержит ссылку на изменяемый объект, его значение изменяется при изменении этого изменяемого объекта.
Типы влияют практически на все аспекты поведения объектов. В некотором смысле это влияет даже на важность идентификации объекта: для неизменяемых типов операции, которые вычисляют новые значения, могут фактически возвращать ссылку на любой существующий объект с тем же типом и значением, в то время как для изменяемых объектов это недопустимо. Например, после a = 1; b = 1
, a
и b
могут ссылаться или не ссылаться на один и тот же объект со значением one, в зависимости от реализации, но после c = []; d = []
, c
и d
гарантированно ссылаются на два разных, уникальных, недавно созданных пустых списка. (Обратите внимание, что c = d = []
присваивает один и тот же объект как c
, так и d
.)
3.2. Иерархия стандартных типов¶
Ниже приведен список типов, встроенных в Python. Модули расширения (написанные на C, Java или других языках, в зависимости от реализации) могут определять дополнительные типы. Будущие версии Python могут добавить типы в иерархию типов (например, рациональные числа, эффективно сохраняемые массивы целых чисел и т.д.), хотя такие дополнения часто будут предоставляться через стандартную библиотеку.
Некоторые из приведенных ниже описаний типов содержат абзац со списком «специальных атрибутов». Это атрибуты, которые предоставляют доступ к реализации и не предназначены для общего использования. Их определение может измениться в будущем.
3.2.1. Никто¶
Этот тип имеет единственное значение. Существует единственный объект с таким значением. Доступ к этому объекту осуществляется через встроенное имя None
. Оно используется для обозначения отсутствия значения во многих ситуациях, например, оно возвращается из функций, которые явно ничего не возвращают. Его истинностное значение равно false.
3.2.2. Не реализовано¶
Этот тип имеет единственное значение. Существует единственный объект с таким значением. Доступ к этому объекту осуществляется через встроенное имя NotImplemented
. Числовые методы и расширенные методы сравнения должны возвращать это значение, если они не реализуют операцию для предоставленных операндов. (Затем интерпретатор попробует выполнить отраженную операцию или какой-либо другой резервный вариант, в зависимости от оператора.) Это не должно вычисляться в логическом контексте.
Смотрите Выполнение арифметических операций для получения более подробной информации.
Изменено в версии 3.9: Вычисление NotImplemented
в логическом контексте не рекомендуется. Хотя в настоящее время оно оценивается как true, оно будет выдавать значение DeprecationWarning
. В будущей версии Python оно вызовет значение TypeError
.
3.2.3. Эллипс¶
Этот тип имеет единственное значение. Существует единственный объект с таким значением. Доступ к этому объекту осуществляется с помощью литерала ...
или встроенного имени Ellipsis
. Его истинностным значением является true.
3.2.4. numbers.Number
¶
Они создаются с помощью числовых литералов и возвращаются в виде результатов арифметическими операторами и встроенными арифметическими функциями. Числовые объекты неизменяемы; после создания их значение никогда не меняется. Числа в Python, конечно, тесно связаны с математическими числами, но подвержены ограничениям, связанным с числовым представлением в компьютерах.
Строковые представления числовых классов, вычисляемые с помощью __repr__()
и __str__()
, обладают следующими свойствами:
Это допустимые числовые литералы, которые при передаче в конструктор своего класса создают объект, имеющий значение исходного числового значения.
По возможности, представление осуществляется в базе данных 10.
Начальные нули, возможно, за исключением единственного нуля перед десятичной точкой, не отображаются.
Конечные нули, возможно, за исключением одного нуля после запятой, не отображаются.
Знак отображается только в том случае, если число отрицательное.
Python различает целые числа, числа с плавающей запятой и комплексные числа:
3.2.4.1. numbers.Integral
¶
Они представляют собой элементы математического набора целых чисел (положительных и отрицательных).
Примечание
Правила для представления целых чисел предназначены для того, чтобы дать наиболее осмысленную интерпретацию операций сдвига и маскировки, связанных с отрицательными целыми числами.
Существует два типа целых чисел:
- Целые числа (
int
) Они представляют собой числа в неограниченном диапазоне, зависящем только от доступной (виртуальной) памяти. Для целей операций сдвига и маскирования предполагается двоичное представление, и отрицательные числа представляются в виде варианта дополнения 2, который создает иллюзию бесконечной последовательности знаковых битов, простирающейся влево.
- Логические значения (
bool
) Они представляют значения истинности False и True. Два объекта, представляющие значения
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
.
Последовательности также поддерживают нарезку: a[i:j]
выбирает все элементы с индексом k таким образом, что i <=
k <
j. При использовании в качестве выражения фрагмент представляет собой последовательность того же типа. Приведенный выше комментарий об отрицательных индексах также применим к отрицательным позициям фрагмента.
Некоторые последовательности также поддерживают «расширенную нарезку» с третьим параметром «step»: a[i:j:k]
выбирает все элементы a с индексом x, где x = i + n*k
, n >=
0
и i <=
x <
j.
Последовательности различаются в зависимости от их изменчивости:
3.2.5.1. Неизменяемые последовательности¶
Объект типа неизменяемой последовательности не может быть изменен после его создания. (Если объект содержит ссылки на другие объекты, эти другие объекты могут быть изменяемыми и могут быть изменены; однако набор объектов, на которые непосредственно ссылается неизменяемый объект, не может измениться.)
Следующие типы являются неизменяемыми последовательностями:
- Струнные
Строка - это последовательность значений, представляющих кодовые точки в Юникоде. Все кодовые точки в диапазоне
U+0000 - U+10FFFF
могут быть представлены в виде строки. В Python нет типа char; вместо этого каждая кодовая точка в строке представлена в виде строкового объекта длиной1
. Встроенная функцияord()
преобразует кодовую точку из ее строковой формы в целое число в диапазоне0 - 10FFFF
;chr()
преобразует целое число в диапазоне0 - 10FFFF
в соответствующую длину1
строкового объекта.str.encode()
можно использовать для преобразованияstr
вbytes
, используя заданную кодировку текста, аbytes.decode()
можно использовать для достижения обратного результата.- Кортежи
Элементы кортежа - это произвольные объекты Python. Кортежи из двух или более элементов формируются с помощью списков выражений, разделенных запятыми. Кортеж из одного элемента («синглтон») может быть сформирован путем добавления запятой к выражению (выражение само по себе не создает кортеж, поскольку круглые скобки должны использоваться для группировки выражений). Пустой кортеж может быть образован пустой парой круглых скобок.
- Байты
Объект bytes представляет собой неизменяемый массив. Элементы представляют собой 8-разрядные байты, представленные целыми числами в диапазоне 0 <= x < 256. Для создания объектов bytes можно использовать литералы Bytes (например,
b'abc'
) и встроенный конструкторbytes()
. Кроме того, объекты bytes могут быть преобразованы в строки с помощью методаdecode()
.
3.2.5.2. Изменяемые последовательности¶
Изменяемые последовательности могут быть изменены после их создания. Обозначения подписки и нарезки могут использоваться в качестве цели для операторов assignment и del
(delete).
Примечание
Модуль collections
и array
предоставляют дополнительные примеры изменяемых типов последовательностей.
В настоящее время существует два типа встроенных изменяемых последовательностей:
- Списки
Элементы списка являются произвольными объектами Python. Списки формируются путем помещения списка выражений, разделенных запятыми, в квадратные скобки. (Обратите внимание, что для формирования списков длиной 0 или 1 не требуется никаких особых случаев.)
- Байтовые массивы
Объект bytearray - это изменяемый массив. Они создаются с помощью встроенного конструктора
bytearray()
. Помимо того, что байтовые массивы являются изменяемыми (и, следовательно, недоступными для хэширования), они в остальном обеспечивают тот же интерфейс и функциональность, что и неизменяемые объектыbytes
.
3.2.6. Установленные типы¶
Они представляют собой неупорядоченные, конечные наборы уникальных, неизменяемых объектов. Как таковые, они не могут быть проиндексированы никаким индексом. Однако их можно перебирать, а встроенная функция len()
возвращает количество элементов в наборе. Обычно наборы используются для быстрого тестирования принадлежности, удаления дубликатов из последовательности и вычисления математических операций, таких как пересечение, объединение, разность и симметричная разность.
Для элементов набора применяются те же правила неизменяемости, что и для ключей словаря. Обратите внимание, что числовые типы подчиняются обычным правилам числового сравнения: если два числа сравниваются одинаково (например, 1
и 1.0
), только одно из них может содержаться в наборе.
В настоящее время существует два типа встроенных наборов:
- Наборы
Они представляют собой изменяемый набор. Они создаются встроенным конструктором
set()
и впоследствии могут быть изменены несколькими способами, такими какadd()
.- Замороженные наборы
Они представляют собой неизменяемый набор. Они создаются встроенным конструктором
frozenset()
. Поскольку frozenset является неизменяемым и hashable, его можно снова использовать как элемент другого набора или как ключ словаря.
3.2.7. Отображения¶
Они представляют собой конечные наборы объектов, проиндексированных произвольными наборами индексов. Обозначение с нижним индексом a[k]
выбирает элемент, индексированный с помощью k
, из сопоставления a
; это может использоваться в выражениях и в качестве цели присваиваний или инструкций del
. Встроенная функция len()
возвращает количество элементов в сопоставлении.
В настоящее время существует единственный тип встроенного отображения:
3.2.7.1. Словари¶
Они представляют собой конечные наборы объектов, проиндексированных почти произвольными значениями. Единственными типами значений, неприемлемыми в качестве ключей, являются значения, содержащие списки, словари или другие изменяемые типы, которые сравниваются по значению, а не по идентификатору объекта, причина в том, что эффективная реализация словарей требует, чтобы хэш-значение ключа оставалось постоянным. Числовые типы, используемые для ключей, подчиняются обычным правилам числового сравнения: если два числа сравниваются одинаково (например, 1
и 1.0
), то их можно взаимозаменяемо использовать для индексации одной и той же словарной статьи.
Словари сохраняют порядок вставки, что означает, что ключи будут отображаться в том же порядке, в котором они были последовательно добавлены в словаре. Замена существующего ключа не изменяет порядок, однако удаление ключа и его повторная вставка добавят его в конец, вместо того чтобы сохранить его прежнее место.
Словари изменяемы; они могут быть созданы с помощью обозначения {...}
(см. раздел Отображение словаря).
Модули расширения dbm.ndbm
и dbm.gnu
предоставляют дополнительные примеры типов отображения, как и модуль collections
.
Изменено в версии 3.7: Словари не сохраняли порядок вставки в версиях Python до версии 3.6. В CPython 3.6 порядок вставки был сохранен, но в то время это считалось деталью реализации, а не гарантией языка.
3.2.8. Вызываемые типы¶
Это типы, к которым может быть применена операция вызова функции (см. раздел Звонки):
3.2.8.1. Определяемые пользователем функции¶
Пользовательский функциональный объект создается с помощью определения функции (см. раздел Определения функций). Он должен вызываться со списком аргументов, содержащим то же количество элементов, что и список формальных параметров функции.
3.2.8.1.1. Специальные атрибуты, доступные только для чтения¶
Атрибут |
Значение |
---|---|
|
Ссылка на |
|
Объект cell имеет атрибут |
3.2.8.1.2. Специальные атрибуты, доступные для записи¶
Большинство из этих атрибутов проверяют тип присвоенного значения:
Атрибут |
Значение |
---|---|
|
Строка документации функции или |
|
Имя функции. Смотрите также: |
|
Значение функции qualified name. Смотрите также: Добавлено в версии 3.3. |
|
Имя модуля, в котором была определена функция, или |
|
A |
|
Символ code object, представляющий тело скомпилированной функции. |
|
Пространство имен, поддерживающее атрибуты произвольных функций. Смотрите также: |
|
|
|
A |
Функциональные объекты также поддерживают получение и установку произвольных атрибутов, которые могут быть использованы, например, для присоединения метаданных к функциям. Для получения и установки таких атрибутов используется обычная точечная запись атрибутов.
Детали реализации CPython: Текущая реализация CPython поддерживает только атрибуты функций для пользовательских функций. Атрибуты функций для built-in functions могут быть поддержаны в будущем.
Дополнительную информацию об определении функции можно получить из ее code object (доступного через атрибут __code__
).
3.2.8.2. Методы экземпляра¶
Объект instance method объединяет класс, экземпляр класса и любой вызываемый объект (обычно это определяемая пользователем функция).
Специальные атрибуты, доступные только для чтения:
|
Ссылается на объект экземпляра класса, для которого этот метод имеет значение bound |
|
Ссылается на оригинал function object |
|
Документация к методу (такая же, как |
|
Название метода (такое же, как |
|
Имя модуля, в котором был определен метод, или |
Методы также поддерживают доступ (но не установку) к атрибутам произвольной функции в базовом function object.
Определяемые пользователем объекты метода могут быть созданы при получении атрибута класса (возможно, через экземпляр этого класса), если этот атрибут является определяемым пользователем function object или classmethod
объектом.
Когда объект instance method создается путем извлечения определенного пользователем function object из класса через один из его экземпляров, его атрибутом __self__
является instance, а объект method называется связанным. Атрибутом нового метода __func__
является исходный объект function.
Когда объект метода экземпляра создается путем извлечения объекта 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
является базовой функцией.
Обратите внимание, что преобразование из function object в объект метода экземпляра происходит каждый раз, когда атрибут извлекается из экземпляра. В некоторых случаях оптимизация заключается в присвоении атрибута локальной переменной и вызове этой локальной переменной. Также обратите внимание, что это преобразование выполняется только для пользовательских функций; другие вызываемые объекты (и все не вызываемые объекты) извлекаются без преобразования. Также важно отметить, что пользовательские функции, которые являются атрибутами экземпляра класса, не преобразуются в связанные методы; это происходит только в том случае, если функция является атрибутом класса.
3.2.8.3. Функции генератора¶
Функция или метод, использующий оператор yield
(см. раздел Оператор yield), называется generator function. Такая функция при вызове всегда возвращает iterator объект, который может быть использован для выполнения тела функции: вызов метода итератора iterator.__next__()
приведет к выполнению функции до тех пор, пока она не предоставит значение с использованием yield
заявление. Когда функция выполняет инструкцию return
или не завершает работу, возникает исключение StopIteration
, и итератор достигнет конца набора возвращаемых значений.
3.2.8.4. Функции сопрограммы¶
Функция или метод, который определяется с помощью async def
, называется coroutine function. При вызове такой функции возвращается объект coroutine. Он может содержать await
выражения, а также async with
и async for
утверждения. Смотрите также раздел Объекты сопрограммы.
3.2.8.5. Функции асинхронного генератора¶
Функция или метод, который определяется с помощью async def
и который использует оператор yield
, называется asynchronous generator function. Такая функция при вызове возвращает объект asynchronous iterator, который может быть использован в инструкции async for
для выполнения тела функции.
Вызов метода асинхронных итераторов aiterator.__anext__
вернет значение awaitable, которое при ожидании будет выполняться до тех пор, пока не выдаст значение, используя выражение yield
. Когда функция выполняет пустую инструкцию return
или не завершает выполнение, возникает исключение StopAsyncIteration
, и асинхронный итератор достигнет конца набора значений, которые должны быть получены.
3.2.8.6. Встроенные функции¶
Объект встроенной функции - это оболочка для функции языка Си. Примерами встроенных функций являются len()
и math.sin()
(math
это стандартный встроенный модуль). Количество и тип аргументов определяются функцией C. Специальные атрибуты, доступные только для чтения:
__doc__
- это строка документации к функции, илиNone
, если она недоступна. Смотритеfunction.__doc__
.__name__
- это имя функции. Смотритеfunction.__name__
.__self__
имеет значениеNone
(но смотрите следующий пункт).__module__
- это имя модуля, в котором была определена функция, илиNone
, если функция недоступна. Смотритеfunction.__module__
.
3.2.8.7. Встроенные методы¶
На самом деле это другая маскировка встроенной функции, на этот раз содержащая объект, передаваемый функции C в качестве неявного дополнительного аргумента. Примером встроенного метода является alist.append()
, предполагающий, что alist является объектом списка. В этом случае специальный атрибут, доступный только для чтения __self__
, присваивается объекту, обозначаемому alist. (Этот атрибут имеет ту же семантику, что и атрибут other instance methods
.)
3.2.8.8. Занятия¶
Классы доступны для вызова. Обычно эти объекты действуют как фабрики для создания новых экземпляров самих себя, но возможны варианты для типов классов, которые переопределяют __new__()
. Аргументы вызова передаются в __new__()
и, в типичном случае, в __init__()
для инициализации нового экземпляра.
3.2.8.9. Экземпляры классов¶
Экземпляры произвольных классов можно сделать доступными для вызова, определив метод __call__()
в их классе.
3.2.9. Модули¶
Модули являются базовой организационной единицей кода Python и создаются с помощью команды import system, которая вызывается либо с помощью инструкции import
, либо с помощью вызова таких функций, как importlib.import_module()
и встроенных __import__()
. Объект module имеет пространство имен, реализуемое объектом dictionary
(это словарь, на который ссылается атрибут __globals__
функций, определенных в модуле). Ссылки на атрибуты преобразуются в поисковые запросы в этом словаре, например, m.x
эквивалентно m.__dict__["x"]
. Объект module не содержит объект code, используемый для инициализации модуля (поскольку он не нужен после завершения инициализации).
Присвоение атрибута обновляет словарь пространства имен модуля, например, m.x = 1
эквивалентно m.__dict__["x"] = 1
.
Предопределенные (доступные для записи) атрибуты:
__name__
Название модуля.
__doc__
Строка документации модуля или
None
, если недоступна.__file__
Путь к файлу, из которого был загружен модуль, если он был загружен из файла. Атрибут
__file__
может отсутствовать для определенных типов модулей, таких как модули C, которые статически связаны с интерпретатором. Для модулей расширения, динамически загружаемых из общей библиотеки, это путь к файлу общей библиотеки.__annotations__
Словарь, содержащий variable annotations, собранный во время выполнения основного текста модуля. Для получения рекомендаций по работе с
__annotations__
, пожалуйста, ознакомьтесь с Аннотации к лучшим практикам.
Специальный атрибут, доступный только для чтения: __dict__
- это пространство имен модуля как объекта словаря.
Детали реализации CPython: Из-за того, что CPython очищает словари модулей, словарь модуля будет удален, когда модуль выйдет из области видимости, даже если в словаре все еще есть ссылки на него. Чтобы избежать этого, скопируйте словарь или сохраните модуль, используя его словарь напрямую.
3.2.10. Пользовательские классы¶
Пользовательские типы классов обычно создаются с помощью определений классов (см. раздел Определения классов). Класс имеет пространство имен, реализуемое объектом словаря. Ссылки на атрибуты класса преобразуются в поисковые запросы в этом словаре, например, C.x
преобразуется в C.__dict__["x"]
(хотя существует ряд перехватчиков, которые позволяют использовать другие способы поиска атрибутов). Если имя атрибута там не найдено, поиск атрибута продолжается в базовых классах. Этот поиск по базовым классам использует метод C3 resolution order, который корректно работает даже при наличии структур наследования типа «ромб», где существует несколько путей наследования, ведущих к общему предку. Дополнительные сведения о C3 MRO, используемом Python, можно найти в документации, сопровождающей выпуск 2.3, по адресу https://www.python.org/download/releases/2.3/mro/.
Когда ссылка на атрибут класса (например, для класса C
) приводит к объекту метода класса, он преобразуется в объект метода экземпляра, атрибутом которого __self__
является C
. Когда он выдает объект staticmethod
, он преобразуется в объект, обернутый статическим методом object. Смотрите раздел Реализация дескрипторов о другом способе, которым атрибуты, извлекаемые из класса, могут отличаться от тех, которые фактически содержатся в его __dict__
.
Присвоения атрибутов класса обновляют словарь класса, а не словарь базового класса.
Объект класса может быть вызван (см. выше) для получения экземпляра класса (см. ниже).
Особые атрибуты:
__name__
Название класса.
__module__
Имя модуля, в котором был определен класс.
__dict__
Словарь, содержащий пространство имен класса.
__bases__
Кортеж, содержащий базовые классы в порядке их появления в списке базовых классов.
__doc__
Строка документации класса или
None
, если не определено.__annotations__
Словарь, содержащий variable annotations, собранный во время выполнения основного текста класса. Для получения рекомендаций по работе с
__annotations__
, пожалуйста, ознакомьтесь с Аннотации к лучшим практикам.
3.2.11. Экземпляры классов¶
Экземпляр класса создается путем вызова объекта класса (см. выше). Экземпляр класса имеет пространство имен, реализованное в виде словаря, который является первым местом, в котором выполняется поиск ссылок на атрибуты. Если атрибут там не найден, а класс экземпляра имеет атрибут с таким именем, поиск продолжается по атрибутам класса. Если обнаружен атрибут class, который является определяемым пользователем функциональным объектом, он преобразуется в объект instance method, атрибутом которого __self__
является экземпляр. Объекты Static method и class method также преобразуются; смотрите выше в разделе «Классы». Смотрите раздел Реализация дескрипторов о другом способе, которым атрибуты класса, извлекаемые через его экземпляры, могут отличаться от объектов, фактически хранящихся в __dict__
класса. Если атрибут class не найден, а класс объекта имеет метод __getattr__()
, который вызывается для выполнения запроса.
Присвоение и удаление атрибутов приводит к обновлению словаря экземпляра, но не словаря класса. Если в классе есть метод __setattr__()
или __delattr__()
, он вызывается вместо непосредственного обновления словаря экземпляра.
Экземпляры классов могут выдавать себя за числа, последовательности или отображения, если у них есть методы с определенными специальными именами. Смотрите раздел Названия специальных методов.
Специальные атрибуты: __dict__
- это словарь атрибутов; __class__
- это класс экземпляра.
3.2.12. Объекты ввода-вывода (также известные как файловые объекты)¶
Символ file object представляет собой открытый файл. Для создания файловых объектов доступны различные сочетания клавиш: встроенная функция open()
, а также os.popen()
, os.fdopen()
, и метод makefile()
объектов socket (и, возможно, с помощью других функций или методов, предоставляемых модулями расширения).
Объекты sys.stdin
, sys.stdout
и sys.stderr
инициализируются как файловые объекты, соответствующие стандартным потокам ввода, вывода и ошибок интерпретатора; все они открыты в текстовом режиме и, следовательно, следуют интерфейсу, определяемому абстрактным классом io.TextIOBase
.
3.2.13. Внутренние типы¶
Некоторые типы, используемые внутри интерпретатора, доступны пользователю. Их определения могут изменяться в будущих версиях интерпретатора, но они упомянуты здесь для полноты картины.
3.2.13.1. Объекты кода¶
Объекты Code представляют собой байт-скомпилированный исполняемый код Python, или bytecode. Разница между объектом code и объектом function заключается в том, что объект function содержит явную ссылку на глобальные параметры функции (модуль, в котором она была определена), в то время как объект code не содержит контекста; кроме того, значения аргументов по умолчанию хранятся в объекте function, а не в объекте code (потому что они представляют собой значения, вычисленные во время выполнения). В отличие от функциональных объектов, объекты кода являются неизменяемыми и не содержат ссылок (прямых или косвенных) на изменяемые объекты.
3.2.13.1.1. Специальные атрибуты, доступные только для чтения¶
|
Имя функции |
|
Полное имя функции Добавлено в версии 3.11. |
|
Общее количество позиционных parameters (включая только позиционные параметры и параметры со значениями по умолчанию), которые имеет функция |
|
Количество только позиционных parameters (включая аргументы со значениями по умолчанию), которые имеет функция |
|
Количество доступных функции только для ключевых слов parameters (включая аргументы со значениями по умолчанию) |
|
Количество local variables, используемых функцией (включая параметры) |
|
A |
|
A |
|
A |
|
Строка, представляющая последовательность bytecode инструкций в функции |
|
A |
|
|
|
Имя файла, из которого был скомпилирован код |
|
Номер строки первой строки функции |
|
Строка, кодирующая отображение из bytecode, преобразуется в номера строк. Более подробную информацию смотрите в исходном коде интерпретатора. |
|
Требуемый размер стека объекта code |
|
|
Для co_flags
определены следующие биты флага: бит 0x04
устанавливается, если функция использует синтаксис *arguments
для приема произвольного числа позиционных аргументов; бит 0x08
устанавливается, если функция использует синтаксис **keywords
для приема произвольных аргументов ключевого слова; бит 0x20
устанавливается, если функция является генератором. Смотрите Битовые флаги объектов кода для получения подробной информации о семантике каждого из флагов, которые могут присутствовать.
В будущих объявлениях функций (from __future__ import division
) также используются биты в co_flags
, чтобы указать, был ли объект кода скомпилирован с включенной определенной функцией: бит 0x2000
устанавливается, если функция была скомпилирована с включенным разделением в будущем; биты 0x10
и 0x1000
использовались в более ранних версиях Python.
Другие биты в co_flags
зарезервированы для внутреннего использования.
Если объект кода представляет функцию, то первым элементом в co_consts
является строка документации функции или None
, если не определено.
3.2.13.1.2. Методы для объектов кода¶
- codeobject.co_positions()¶
Возвращает итерацию по позициям исходного кода каждой инструкции bytecode в объекте code.
Итератор возвращает
tuple
s, содержащий(start_line, end_line, start_column, end_column)
. i-й кортеж соответствует позиции исходного кода, который был скомпилирован в i-й блок кода. Информация о столбце представляет собой 0-индексированные значения utf-8 байтовых смещений в данной исходной строке.Эта информация о местоположении может отсутствовать. Неполный список случаев, когда это может произойти:
Запуск интерпретатора с помощью
-X
no_debug_ranges
.Загрузка файла pyc, скомпилированного при использовании
-X
no_debug_ranges
.Расположите кортежи, соответствующие искусственным инструкциям.
Номера строк и столбцов, которые не могут быть представлены из-за специфических ограничений реализации.
Когда это происходит, некоторые или все элементы кортежа могут быть
None
.Добавлено в версии 3.11.
Примечание
Эта функция требует сохранения позиций столбцов в объектах кода, что может привести к небольшому увеличению использования диска скомпилированными файлами Python или памяти интерпретатора. Чтобы избежать сохранения дополнительной информации и/или отключить печать дополнительной информации обратной трассировки, можно использовать флаг командной строки
-X
no_debug_ranges
или переменную окруженияPYTHONNODEBUGRANGES
.
- codeobject.co_lines()¶
Возвращает итератор, который выдает информацию о последовательных диапазонах bytecodeс. Каждый полученный элемент представляет собой
(start, end, lineno)
tuple
:start
(int
) представляет собой смещение (включительно) от начала диапазона bytecodeend
(int
) представляет собой смещение (исключительное) конца диапазона bytecodelineno
- этоint
, представляющий номер строки диапазона bytecode, илиNone
, если байт-коды в данном диапазоне не имеют номера строки
Полученные элементы будут обладать следующими свойствами:
Первый полученный диапазон будет иметь значение
start
, равное 0.Диапазоны
(start, end)
будут неубывающими и последовательными. То есть для любой парыtuple
s значениеstart
второго будет равно значениюend
первого.Ни один диапазон не будет изменен в обратном направлении:
end >= start
для всех троек.Последний полученный
tuple
будет иметь размерend
, равный размеру bytecode.
Допустимы диапазоны нулевой ширины, где
start == end
. Диапазоны нулевой ширины используются для строк, которые присутствуют в исходном коде, но были удалены компилятором bytecode.Добавлено в версии 3.10.
См.также
- PEP 626 - Точные номера строк для отладки и других инструментов.
ОПТОСОЗ, который ввел метод
co_lines()
.
- codeobject.replace(**kwargs)¶
Возвращает копию объекта code с новыми значениями для указанных полей.
Добавлено в версии 3.8.
3.2.13.2. Обрамляющие объекты¶
Объекты Frame представляют собой фреймы выполнения. Они могут встречаться в traceback objects, а также передаваться зарегистрированным функциям трассировки.
3.2.13.2.1. Специальные атрибуты, доступные только для чтения¶
|
Указывает на предыдущий кадр стека (по направлению к вызывающей стороне) или |
|
В этом кадре выполняется code object. При обращении к этому атрибуту возникает auditing event |
|
Словарь, используемый фреймом для поиска local variables |
|
Словарь, используемый фреймом для поиска global variables |
|
Словарь, используемый фреймом для поиска built-in (intrinsic) names |
|
«Точная инструкция» объекта frame (это индекс в bytecode строке code object) |
3.2.13.2.2. Специальные атрибуты, доступные для записи¶
|
Если нет |
|
Установите для этого атрибута значение |
|
Установите для этого атрибута значение |
|
Текущий номер строки фрейма - запись в него из функции трассировки приводит к переходу на заданную строку (только для самого нижнего фрейма). Отладчик может реализовать команду перехода (она же инструкция Set Next), записав ее в этот атрибут. |
3.2.13.2.3. Методы создания фреймового объекта¶
Объекты Frame поддерживают один метод:
- frame.clear()¶
Этот метод удаляет все ссылки на local variables, содержащиеся в кадре. Кроме того, если кадр принадлежит generator, генератор завершает работу. Это помогает разорвать циклы ссылок, связанные с объектами frame (например, при перехвате exception и сохранении его traceback для последующего использования).
RuntimeError
вызывается, если в данный момент выполняется кадр.Добавлено в версии 3.4.
3.2.13.3. Объекты обратной трассировки¶
Объекты обратной трассировки представляют собой трассировку стека exception. Объект обратной трассировки неявно создается при возникновении исключения, а также может быть явно создан с помощью вызова types.TracebackType
.
Изменено в версии 3.7: Объекты обратной трассировки теперь могут быть явно созданы из кода Python.
Для неявно созданных обратных трассировок, когда поиск обработчика исключений разворачивает стек выполнения, на каждом уровне развертывания объект обратной трассировки вставляется перед текущим объектом обратной трассировки. Когда вводится обработчик исключений, трассировка стека становится доступной для программы. (Смотрите раздел Оператор try.) Он доступен как третий элемент кортежа, возвращаемый sys.exc_info()
, и как атрибут __traceback__
перехваченного исключения.
Когда программа не содержит подходящего обработчика, трассировка стека записывается (в удобном формате) в стандартный поток ошибок; если интерпретатор интерактивен, он также становится доступным пользователю как sys.last_traceback
.
Для явно созданных обратных трассировок создатель обратной трассировки должен определить, как должны быть связаны атрибуты tb_next
для формирования полной трассировки стека.
Специальные атрибуты, доступные только для чтения:
|
Указывает на выполнение frame текущего уровня. При обращении к этому атрибуту возникает auditing event |
|
Указывает номер строки, в которой произошло исключение |
|
Указывает на «точную инструкцию». |
Номер строки и последняя инструкция в обратной трассировке могут отличаться от номера строки в frame object, если исключение возникло в инструкции try
без соответствующего предложения except или с предложением finally
.
- traceback.tb_next¶
Специальный атрибут, доступный для записи
tb_next
, указывает на следующий уровень трассировки стека (по направлению к кадру, в котором произошло исключение) илиNone
, если следующего уровня нет.Изменено в версии 3.7: Теперь этот атрибут доступен для записи
3.2.13.4. Объекты среза¶
Объекты Slice используются для представления срезов для методов __getitem__()
. Они также создаются с помощью встроенной функции slice()
.
Специальные атрибуты, доступные только для чтения: start
- нижняя граница; stop
- верхняя граница; step
- значение шага; каждый из них равен None
, если он опущен. Эти атрибуты могут иметь любой тип.
Объекты Slice поддерживают один метод:
- slice.indices(self, length)¶
Этот метод принимает единственный целочисленный аргумент length и вычисляет информацию о срезе, которую описал бы объект slice, если бы он был применен к последовательности элементов length. Он возвращает набор из трех целых чисел; соответственно, это индексы start и stop, а также step или длина шага фрагмента. Отсутствующие индексы или индексы, выходящие за границы, обрабатываются в соответствии с обычными фрагментами.
3.2.13.5. Объекты статического метода¶
Статические объекты method предоставляют способ избежать преобразования объектов function в объекты method, описанный выше. Статический объект method - это оболочка для любого другого объекта, обычно определяемого пользователем объекта method. Когда объект статического метода извлекается из класса или экземпляра класса, фактически возвращаемый объект является обернутым объектом, который не подлежит дальнейшему преобразованию. Объекты статического метода также доступны для вызова. Объекты статического метода создаются встроенным конструктором staticmethod()
.
3.2.13.6. Объекты метода класса¶
Объект class method, как и объект static method, является оболочкой для другого объекта, которая изменяет способ извлечения этого объекта из классов и экземпляров класса. Поведение объектов class method при таком извлечении описано выше, в разделе «instance methods». Объекты метода класса создаются с помощью встроенного конструктора classmethod()
.
3.3. Названия специальных методов¶
Класс может реализовывать определенные операции, которые вызываются с помощью специального синтаксиса (например, арифметические операции или индексирование и нарезка), определяя методы со специальными именами. Это подход Python к operator overloading, позволяющий классам определять свое собственное поведение по отношению к языковым операторам. Например, если класс определяет метод с именем __getitem__()
, а x
является экземпляром этого класса, то x[i]
примерно эквивалентно type(x).__getitem__(x, i)
. За исключением случаев, когда указано иное, попытки выполнить операцию вызывают исключение, когда не определен соответствующий метод (обычно AttributeError
или TypeError
).
Установка специального метода в None
означает, что соответствующая операция недоступна. Например, если класс устанавливает для __iter__()
значение None
, класс не поддается итерации, поэтому вызов iter()
для его экземпляров приведет к TypeError
(без возврата к __getitem__()
). [2]
При реализации класса, который эмулирует любой встроенный тип, важно, чтобы эмуляция была реализована только в той степени, в какой это имеет смысл для моделируемого объекта. Например, некоторые последовательности могут хорошо работать с извлечением отдельных элементов, но извлечение фрагмента может не иметь смысла. (Одним из примеров этого является интерфейс NodeList
в объектной модели документа W3C.)
3.3.1. Базовая настройка¶
- object.__new__(cls[, ...])¶
Вызывается для создания нового экземпляра класса cls.
__new__()
- это статический метод (в специальном регистре, поэтому вам не нужно объявлять его как таковой), который принимает класс, экземпляр которого был запрошен, в качестве первого аргумента. Остальные аргументы передаются в выражение конструктора объекта (вызов класса). Возвращаемое значение__new__()
должно быть новым экземпляром объекта (обычно это экземпляр cls).Типичные реализации создают новый экземпляр класса, вызывая метод superclass
__new__()
с использованиемsuper().__new__(cls[, ...])
с соответствующими аргументами, а затем изменяя вновь созданный экземпляр по мере необходимости перед его возвратом.Если
__new__()
вызывается во время создания объекта и возвращает экземпляр cls, то метод нового экземпляра__init__()
будет вызван как__init__(self[, ...])
, где self - это новый экземпляр и остальные аргументы являются теми же самыми, которые были переданы конструктору объекта.Если
__new__()
не возвращает экземпляр cls, то метод new instances__init__()
вызываться не будет.__new__()
предназначен в основном для того, чтобы позволить подклассам неизменяемых типов (например, int, str или tuple) настраивать создание экземпляров. Он также обычно переопределяется в пользовательских метаклассах, чтобы настраивать создание классов.
- object.__init__(self[, ...])¶
Вызывается после создания экземпляра (с помощью
__new__()
), но до того, как он будет возвращен вызывающей стороне. Аргументами являются аргументы, переданные в выражение конструктора класса. Если у базового класса есть метод__init__()
, метод__init__()
производного класса, если таковой имеется, должен явно вызывать его, чтобы обеспечить правильную инициализацию части экземпляра базового класса; например:super().__init__([args...])
.Поскольку
__new__()
и__init__()
работают совместно при создании объектов (__new__()
для их создания и__init__()
для их настройки), значение, отличное отNone
, не может быть возвращено с помощью__init__()
; это приведет к появлениюTypeError
во время выполнения.
- object.__del__(self)¶
Вызывается, когда экземпляр вот-вот будет уничтожен. Это также называется завершителем или (неправильно) деструктором. Если у базового класса есть метод
__del__()
, то метод производного класса__del__()
, если таковой имеется, должен явно вызывать его, чтобы обеспечить надлежащее удаление части экземпляра, относящейся к базовому классу.Для метода
__del__()
возможно (хотя и не рекомендуется!) отложить уничтожение экземпляра, создав новую ссылку на него. Это называется object resurrection. От реализации зависит, вызывается ли__del__()
во второй раз, когда воскресший объект вот-вот будет уничтожен; текущая реализация CPython вызывает его только один раз.Не гарантируется, что методы
__del__()
будут вызваны для объектов, которые все еще существуют при завершении работы интерпретатора.Примечание
del x
не вызывает напрямуюx.__del__()
— первый уменьшает количество ссылок дляx
на единицу, а второй вызывается только тогда, когда количество ссылок дляx
достигает нуля.Детали реализации CPython: Цикл ссылок может предотвратить обнуление значения счетчика ссылок для объекта. В этом случае цикл будет позже обнаружен и удален с помощью cyclic garbage collector. Частой причиной циклов ссылок является перехват исключения в локальной переменной. Локальные значения фрейма затем ссылаются на исключение, которое ссылается на свою собственную обратную трассировку, которая ссылается на локальные значения всех фреймов, перехваченных в ходе обратной трассировки.
См.также
Документация к модулю
gc
.Предупреждение
Из-за нестабильных условий, при которых вызываются методы
__del__()
, исключения, возникающие во время их выполнения, игнорируются, а вместо этого выводится предупреждениеsys.stderr
. В частности:__del__()
может быть вызван при выполнении произвольного кода, в том числе из любого произвольного потока. Если__del__()
необходимо снять блокировку или вызвать любой другой блокирующий ресурс, это может привести к взаимоблокировке, поскольку ресурс уже может быть занят кодом, выполнение которого прерывается__del__()
.__del__()
может быть выполнено во время завершения работы интерпретатора. Как следствие, глобальные переменные, к которым ему необходим доступ (включая другие модули), возможно, уже удалены или им присвоено значениеNone
. Python гарантирует, что глобальные переменные, имя которых начинается с одного символа подчеркивания, будут удалены из их модуля до удаления других глобальных переменных; если других ссылок на такие глобальные переменные не существует, это может помочь гарантировать, что импортированные модули все еще доступны во время вызова метода__del__()
.
- object.__repr__(self)¶
Вызывается встроенной функцией
repr()
для вычисления «официального» строкового представления объекта. Если это вообще возможно, это должно выглядеть как допустимое выражение Python, которое можно было бы использовать для воссоздания объекта с тем же значением (при наличии соответствующей среды). Если это невозможно, должна быть возвращена строка вида<...some useful description...>
. Возвращаемое значение должно быть строковым объектом. Если класс определяет__repr__()
, но не__str__()
, то__repr__()
также используется, когда требуется «неформальное» строковое представление экземпляров этого класса.Обычно это используется для отладки, поэтому важно, чтобы представление было информационно насыщенным и недвусмысленным.
- object.__str__(self)¶
Вызывается с помощью
str(object)
и встроенных функцийformat()
иprint()
для вычисления «неформального» или удобного для печати строкового представления объекта. Возвращаемое значение должно быть string object.Этот метод отличается от
object.__repr__()
тем, что нет ожидания, что__str__()
вернет корректное выражение Python: можно использовать более удобное или сжатое представление.Реализация по умолчанию, определенная встроенным типом
object
, вызываетobject.__repr__()
.
- object.__bytes__(self)¶
Вызывается с помощью bytes для вычисления представления объекта в виде байтовой строки. Это должно возвращать объект
bytes
.
- object.__format__(self, format_spec)¶
Вызывается встроенной функцией
format()
и, как следствие, вычислением метода formatted string literals и методаstr.format()
для получения «отформатированного» строкового представления объекта. Аргумент format_spec - это строка, содержащая описание желаемых параметров форматирования. Интерпретация аргумента format_spec зависит от типа, реализующего__format__()
, однако большинство классов либо делегируют форматирование одному из встроенных типов, либо используют аналогичный синтаксис параметров форматирования.Описание стандартного синтаксиса форматирования приведено в разделе Мини-язык спецификации формата.
Возвращаемое значение должно быть строковым объектом.
Изменено в версии 3.4: Метод __format__ из
object
сам генерируетTypeError
, если передается любая непустая строка.Изменено в версии 3.7:
object.__format__(x, '')
теперь эквивалентноstr(x)
, а неformat(str(x), '')
.
- object.__lt__(self, other)¶
- object.__le__(self, other)¶
- object.__eq__(self, other)¶
- object.__ne__(self, other)¶
- object.__gt__(self, other)¶
- object.__ge__(self, other)¶
Это так называемые методы «расширенного сравнения». Соответствие между символами операторов и названиями методов следующее:
x<y
вызовыx.__lt__(y)
,x<=y
вызовыx.__le__(y)
,x==y
вызовыx.__eq__(y)
,x!=y
вызовыx.__ne__(y)
,x>y
вызываетx.__gt__(y)
иx>=y
вызываетx.__ge__(y)
.Метод расширенного сравнения может возвращать синглтон
NotImplemented
, если он не реализует операцию для данной пары аргументов. По соглашению,False
иTrue
возвращаются для успешного сравнения. Однако эти методы могут возвращать любое значение, поэтому, если оператор сравнения используется в логическом контексте (например, в условии инструкцииif
), Python вызоветbool()
для значения, чтобы определить, является ли результат истинным или ложным.По умолчанию
object
реализует__eq__()
с помощьюis
, возвращаяNotImplemented
в случае ложного сравнения:True if x is y else NotImplemented
. Для__ne__()
по умолчанию он делегирует значение__eq__()
и инвертирует результат, если только это неNotImplemented
. Между операторами сравнения или реализациями по умолчанию нет других подразумеваемых взаимосвязей; например, истинность(x<y or x==y)
не подразумеваетx<=y
. Как автоматически генерировать операции упорядочения из одной корневой операции, смотрите в разделеfunctools.total_ordering()
.Смотрите параграф, посвященный
__hash__()
, для некоторых важных замечаний по созданию hashable объектов, которые поддерживают пользовательские операции сравнения и могут использоваться в качестве ключей словаря.У этих методов нет версий с измененными аргументами (которые будут использоваться, когда левый аргумент не поддерживает операцию, а правый аргумент поддерживает); скорее,
__lt__()
и__gt__()
являются отражением друг друга,__le__()
и__ge__()
являются отражением друг друга, а__eq__()
и__ne__()
являются их собственными отражениями. Если операнды имеют разные типы и тип правого операнда является прямым или косвенным подклассом типа левого операнда, приоритет имеет отраженный метод правого операнда, в противном случае приоритет имеет метод левого операнда. Виртуальное подклассирование не рассматривается.Когда ни один из подходящих методов не возвращает никакого значения, отличного от
NotImplemented
, операторы==
и!=
возвращаются кis
иis not
соответственно.
- object.__hash__(self)¶
Вызывается встроенной функцией
hash()
и используется для операций с элементами хэшированных коллекций, включаяset
,frozenset
, иdict
. Метод__hash__()
должен возвращать целое число. Единственным обязательным свойством является то, что объекты, которые сравниваются равными, имеют одинаковое хэш-значение; рекомендуется смешивать хэш-значения компонентов объекта, которые также играют роль в сравнении объектов, упаковывая их в кортеж и хэшируя кортеж. Пример:def __hash__(self): return hash((self.name, self.nick, self.color))
Примечание
hash()
обрезает значение, возвращаемое пользовательским методом объекта__hash__()
, до размера aPy_ssize_t
. Обычно это 8 байт в 64-разрядных сборках и 4 байта в 32-разрядных сборках. Если объект__hash__()
должен взаимодействовать с сборками разного размера, обязательно проверьте ширину во всех поддерживаемых сборках. Самый простой способ сделать это - с помощьюpython -c "import sys; print(sys.hash_info.width)"
.Если класс не определяет метод
__eq__()
, он также не должен определять операцию__hash__()
; если он определяет__eq__()
, но не__hash__()
, его экземпляры не будут использоваться в качестве элементов в hashable коллекции. Если класс определяет изменяемые объекты и реализует метод__eq__()
, он не должен реализовывать метод__hash__()
, поскольку реализация коллекций hashable требует, чтобы хэш-значение ключа было неизменяемым (если хэш-значение объекта изменяется, это будет не в том хэш-ведре).Определяемые пользователем классы по умолчанию имеют методы
__eq__()
и__hash__()
; с их помощью все объекты сравниваются неравномерно (кроме самих себя), аx.__hash__()
возвращает соответствующее значение, так чтоx == y
подразумевает, чтоx is y
иhash(x) == hash(y)
.Класс, который переопределяет
__eq__()
и не определяет__hash__()
, будет иметь для__hash__()
неявное значениеNone
. Когда__hash__()
метод класса равенNone
, экземпляры класса будут генерировать соответствующийTypeError
, когда программа попытается получить их хэш-значение, а также будут правильно идентифицированы как недоступные для хэширования при проверкеisinstance(obj, collections.abc.Hashable)
.Если класс, который переопределяет
__eq__()
, должен сохранить реализацию__hash__()
из родительского класса, интерпретатору необходимо сообщить об этом явно, установив__hash__ = <ParentClass>.__hash__
.Если класс, который не переопределяет
__eq__()
, желает отключить поддержку хэша, он должен включить__hash__ = None
в определение класса. Класс, который определяет свой собственный__hash__()
, который явно вызываетTypeError
, будет неправильно идентифицирован как хэшируемый при вызовеisinstance(obj, collections.abc.Hashable)
.Примечание
По умолчанию значения
__hash__()
объектов str и bytes «засаливаются» непредсказуемым случайным значением. Хотя они остаются постоянными в рамках отдельного процесса Python, они непредсказуемы при повторных вызовах Python.Это предназначено для обеспечения защиты от отказа в обслуживании, вызванного тщательно подобранными входными данными, которые используют наихудшую производительность при вставке dict, O(n2) сложность. Подробности смотрите в разделе http://ocert.org/advisories/ocert-2011-003.html.
Изменение значений хэша влияет на порядок итераций наборов. Python никогда не давал гарантий относительно такого порядка (и обычно он варьируется между 32-разрядными и 64-разрядными сборками).
Смотрите также
PYTHONHASHSEED
.Изменено в версии 3.3: По умолчанию включена рандомизация хэша.
- object.__bool__(self)¶
Вызывается для реализации проверки истинности значения и встроенной операции
bool()
; должен возвращатьFalse
илиTrue
. Когда этот метод не определен, вызывается__len__()
, если он определен, и объект считается истинным, если его результат отличен от нуля. Если класс не определяет ни__len__()
, ни__bool__()
, все его экземпляры считаются истинными.
3.3.2. Настройка доступа к атрибутам¶
Следующие методы могут быть определены для настройки значения доступа к атрибуту (использование, присвоение или удаление x.name
) для экземпляров класса.
- object.__getattr__(self, name)¶
Вызывается, когда при доступе к атрибуту по умолчанию происходит сбой с
AttributeError
(либо__getattribute__()
вызываетAttributeError
, потому что name не является атрибутом экземпляра или атрибутом в дереве классов дляself
; или__get__()
свойства name вызываетAttributeError
). Этот метод должен либо возвращать (вычисленное) значение атрибута, либо вызывать исключениеAttributeError
.Обратите внимание, что если атрибут найден с помощью обычного механизма,
__getattr__()
не вызывается. (Это намеренная асимметрия между__getattr__()
и__setattr__()
.) Это сделано как из соображений эффективности, так и потому, что в противном случае у__getattr__()
не было бы возможности получить доступ к другим атрибутам экземпляра. Обратите внимание, что, по крайней мере, для переменных экземпляра вы можете полностью контролировать их, не вставляя никаких значений в словарь атрибутов экземпляра (а вместо этого вставляя их в другой объект). Смотрите приведенный ниже метод__getattribute__()
, чтобы получить полный контроль над доступом к атрибутам.
- object.__getattribute__(self, name)¶
Вызывается безоговорочно для реализации доступа к атрибутам для экземпляров класса. Если класс также определяет
__getattr__()
, последний не будет вызван, если только__getattribute__()
не вызовет его явно или не вызоветAttributeError
. Этот метод должен возвращать (вычисленное) значение атрибута или вызывать исключениеAttributeError
. Чтобы избежать бесконечной рекурсии в этом методе, его реализация всегда должна вызывать метод базового класса с тем же именем для доступа к любым необходимым атрибутам, например,object.__getattribute__(self, name)
.Примечание
Этот метод все еще может быть пропущен при поиске специальных методов в результате неявного вызова с помощью синтаксиса языка или built-in functions. Смотрите Поиск по специальному методу.
Создает auditing event
object.__getattr__
с аргументамиobj
,name
.
- object.__setattr__(self, name, value)¶
Вызывается при попытке присвоения атрибута. Это вызывается вместо обычного механизма (т.е. сохранения значения в справочнике экземпляра). name - это имя атрибута, value - значение, которое ему присваивается.
Если
__setattr__()
требуется присвоить атрибуту экземпляра, он должен вызвать метод базового класса с тем же именем, например,object.__setattr__(self, name, value)
.Создает auditing event
object.__setattr__
с аргументамиobj
,name
,value
.
- object.__delattr__(self, name)¶
Как
__setattr__()
, но для удаления атрибута вместо присвоения. Это должно быть реализовано только в том случае, еслиdel obj.name
имеет значение для объекта.Создает auditing event
object.__delattr__
с аргументамиobj
,name
.
- object.__dir__(self)¶
Вызывается при вызове
dir()
для объекта. Должна быть возвращена повторяемая переменная.dir()
преобразует возвращаемую повторяемую переменную в список и сортирует его.
3.3.2.1. Настройка доступа к атрибутам модуля¶
Специальные имена __getattr__
и __dir__
также могут использоваться для настройки доступа к атрибутам модуля. Функция __getattr__
на уровне модуля должна принимать один аргумент, который является именем атрибута, и возвращать вычисленное значение или вызывать AttributeError
. Если атрибут не найден в объекте модуля с помощью обычного поиска, т.е. object.__getattribute__()
, то __getattr__
выполняется поиск в модуле __dict__
перед вызовом AttributeError
. Если он найден, то вызывается с именем атрибута и возвращается результат.
Функция __dir__
не должна принимать никаких аргументов и возвращать повторяемую строку, представляющую имена, доступные в модуле. Если она присутствует, то эта функция переопределяет стандартный поиск по модулю dir()
.
Для более детальной настройки поведения модуля (настройки атрибутов, свойств и т.д.) можно присвоить атрибуту __class__
объекта модуля значение подкласса types.ModuleType
. Например:
import sys
from types import ModuleType
class VerboseModule(ModuleType):
def __repr__(self):
return f'Verbose {self.__name__}'
def __setattr__(self, attr, value):
print(f'Setting {attr}...')
super().__setattr__(attr, value)
sys.modules[__name__].__class__ = VerboseModule
Примечание
Определение модуля __getattr__
и настройка модуля __class__
влияют только на поиск, выполняемый с использованием синтаксиса доступа к атрибутам - прямой доступ к глобальным параметрам модуля (будь то с помощью кода внутри модуля или через ссылку на словарь глобальных параметров модуля) остается неизменным.
Изменено в версии 3.5: __class__
атрибут модуля теперь доступен для записи.
Добавлено в версии 3.7: __getattr__
и __dir__
атрибуты модуля.
См.также
- PEP 562 - Модуль __getattr__ и __dir__
Описывает функции
__getattr__
и__dir__
в модулях.
3.3.2.2. Реализация дескрипторов¶
Следующие методы применяются только в том случае, если экземпляр класса, содержащего метод (так называемый класс-дескриптор), появляется в классе-владельце (дескриптор должен быть либо в словаре класса-владельца, либо в словаре класса для одного из его родительских классов). В приведенных ниже примерах «атрибут» относится к атрибуту, имя которого является ключом свойства в классе owner“ __dict__
.
- object.__get__(self, instance, owner=None)¶
Вызывается для получения атрибута класса-владельца (доступ к атрибуту класса) или экземпляра этого класса (доступ к атрибуту экземпляра). Необязательный аргумент owner - это класс owner, в то время как instance - это экземпляр, через который был осуществлен доступ к атрибуту, или
None
, когда доступ к атрибуту осуществляется через owner.Этот метод должен возвращать вычисленное значение атрибута или вызывать исключение
AttributeError
.PEP 252 указывает, что
__get__()
может вызываться с одним или двумя аргументами. Собственные встроенные дескрипторы Python поддерживают эту спецификацию; однако, вероятно, некоторые сторонние инструменты имеют дескрипторы, для которых требуются оба аргумента. Собственная реализация Python__getattribute__()
всегда передает оба аргумента, независимо от того, требуются они или нет.
- object.__set__(self, instance, value)¶
Вызывается для установки атрибута экземпляра instance класса owner на новое значение value.
Обратите внимание, что добавление
__set__()
или__delete__()
изменяет тип дескриптора на «дескриптор данных». Более подробную информацию смотрите в разделе Вызов дескрипторов.
- object.__delete__(self, instance)¶
Вызывается для удаления атрибута экземпляра instance класса owner.
Экземпляры дескрипторов также могут содержать атрибут __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(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__ позволяют нам явно объявлять элементы данных (например, свойства) и запрещать создание __dict__
и __weakref__ (если они явно не объявлены в __slots__ или не доступны в родительском элементе).
Экономия места при использовании __dict__
может быть значительной. Скорость поиска атрибутов также может быть значительно увеличена.
- object.__slots__¶
Этой переменной класса может быть присвоена строка, повторяемая или последовательность строк с именами переменных, используемыми экземплярами. __slots__ резервирует место для объявленных переменных и предотвращает автоматическое создание
__dict__
и __weakref__ для каждого экземпляра.
Указания по использованию __слотов__:
При наследовании от класса без __slots__ атрибуты экземпляров
__dict__
и __weakref__ всегда будут доступны.Без переменной
__dict__
экземплярам нельзя присваивать новые переменные, не указанные в определении __slots__. При попытке присвоить имя переменной, не включенной в список, возникаетAttributeError
. Если требуется динамическое присвоение новых переменных, то добавьте'__dict__'
к последовательности строк в объявлении __slots__.Без переменной __weakref__ для каждого экземпляра классы, определяющие __slots__, не поддерживают
weak references
для своих экземпляров. Если требуется слабая поддержка ссылок, то добавьте'__weakref__'
к последовательности строк в объявлении __slots__.__слоты__ реализуются на уровне класса путем создания descriptors для каждого имени переменной. В результате атрибуты class нельзя использовать для установки значений по умолчанию для переменных экземпляра, определенных с помощью __slots__; в противном случае атрибут class заменил бы назначение дескриптора.
Действие объявления __slots__ не ограничивается классом, в котором оно определено. __slots__, объявленные в родительских классах, доступны в дочерних классах. Однако дочерние подклассы получат
__dict__
и __weakref__, если они также не определяют __slots__ (которые должны содержать только имена любых дополнительных слотов).Если класс определяет слот, также определенный в базовом классе, переменная экземпляра, определенная в слоте базового класса, недоступна (за исключением случаев, когда ее дескриптор извлекается непосредственно из базового класса). Это делает значение программы неопределенным. В будущем может быть добавлена проверка, чтобы предотвратить это.
TypeError
будет поднят, если для класса, производного от a"variable-length" built-in type
, определены непустые __слоты__, такие какint
,bytes
, иtuple
.Любое значение, отличное от строки iterable, может быть присвоено __slots__.
Если для назначения __слотов__ используется
dictionary
, то в качестве названий слотов будут использоваться ключи словаря. Значения словаря могут быть использованы для предоставления строк документации для каждого атрибута, которые будут распознаватьсяinspect.getdoc()
и отображаться в выходных данныхhelp()
.__class__
присвоение работает только в том случае, если оба класса имеют одинаковые __слоты__.Multiple inheritance с несколькими родительскими классами с прорезями можно использовать, но только одному родительскому классу разрешено иметь атрибуты, созданные слотами (другие базы должны иметь пустые макеты слотов) - нарушения приводят к появлению
TypeError
.Если для __slots__ используется iterator, то для каждого значения итератора создается descriptor. Однако атрибут __slots__ будет пустым итератором.
3.3.3. Настройка создания класса¶
Всякий раз, когда класс наследуется от другого класса, для родительского класса вызывается __init_subclass__()
. Таким образом, можно создавать классы, которые изменяют поведение подклассов. Это тесно связано с декораторами классов, но там, где декораторы классов влияют только на конкретный класс, к которому они применяются, __init_subclass__
применяется исключительно к будущим подклассам класса, определяющего метод.
- classmethod object.__init_subclass__(cls)¶
Этот метод вызывается всякий раз, когда содержащий его класс переходит в подкласс. Тогда cls становится новым подклассом. Если он определен как обычный метод экземпляра, этот метод неявно преобразуется в метод класса.
Аргументы ключевого слова, которые присваиваются новому классу, передаются в
__init_subclass__
родительского класса. Для совместимости с другими классами, использующими__init_subclass__
, следует удалить необходимые аргументы ключевого слова и передать остальные базовому классу, как в:class Philosopher: def __init_subclass__(cls, /, default_name, **kwargs): super().__init_subclass__(**kwargs) cls.default_name = default_name class AustralianPhilosopher(Philosopher, default_name="Bruce"): pass
Реализация по умолчанию
object.__init_subclass__
ничего не делает, но выдает ошибку, если она вызывается с какими-либо аргументами.Примечание
Подсказка о метаклассе
metaclass
используется остальной частью механизма типов и никогда не передается в реализации__init_subclass__
. К фактическому метаклассу (а не к явной подсказке) можно получить доступ как кtype(cls)
.Добавлено в версии 3.6.
Когда класс создан, type.__new__()
сканирует переменные класса и выполняет обратные вызовы для переменных с перехватом __set_name__()
.
- object.__set_name__(self, owner, name)¶
Вызывается автоматически при создании класса-владельца owner. Объекту присвоено имя в этом классе:
class A: x = C() # Automatically calls: x.__set_name__(A, 'x')
Если переменная class назначена после создания класса,
__set_name__()
не будет вызываться автоматически. При необходимости,__set_name__()
может быть вызвана напрямую:class A: pass c = C() A.x = c # The hook is not called c.__set_name__(A, 'x') # Manually invoke the hook
Смотрите Создание объекта класса для получения более подробной информации.
Добавлено в версии 3.6.
3.3.3.1. Метаклассы¶
По умолчанию классы создаются с использованием type()
. Тело класса выполняется в новом пространстве имен, а имя класса локально привязывается к результату type(name, bases, namespace)
.
Процесс создания класса можно настроить, передав аргумент ключевого слова metaclass
в строке определения класса или унаследовав его от существующего класса, который включал такой аргумент. В следующем примере и MyClass
, и MySubclass
являются экземплярами Meta
:
class Meta(type):
pass
class MyClass(metaclass=Meta):
pass
class MySubclass(MyClass):
pass
Любые другие аргументы ключевого слова, указанные в определении класса, передаются во все операции с метаклассами, описанные ниже.
При выполнении определения класса выполняются следующие действия:
Записи ТОИР разрешены;
определен соответствующий метакласс;
пространство имен класса подготовлено;
тело класса выполняется;
объект класса создан.
3.3.3.2. Разрешение ввода данных ТОИР¶
- object.__mro_entries__(self, bases)¶
Если база, которая появляется в определении класса, не является экземпляром
type
, то в базе выполняется поиск метода__mro_entries__()
. Если найден метод__mro_entries__()
, то при создании класса базовый метод заменяется результатом вызова метода__mro_entries__()
. Метод вызывается с исходным кортежем bases, передаваемым в параметр bases, и должен возвращать кортеж классов, которые будут использоваться вместо base. Возвращаемый кортеж может быть пустым: в этих случаях исходная база игнорируется.
См.также
types.resolve_bases()
Динамически разрешать базы, которые не являются экземплярами
type
.- PEP 560
Основная поддержка модуля ввода текста и универсальных типов.
3.3.3.3. Определение соответствующего метакласса¶
Соответствующий метакласс для определения класса определяется следующим образом:
если базы данных и явный метакласс не заданы, то используется
type()
;если задан явный метакласс и он не является экземпляром
type()
, то он используется непосредственно как метакласс;если в качестве явного метакласса указан экземпляр
type()
или определены основания, то используется наиболее производный метакласс.
Наиболее производный метакласс выбирается из явно указанного метакласса (если таковой имеется) и метаклассов (т.е. type(cls)
) всех указанных базовых классов. Наиболее производным метаклассом является тот, который является подтипом всех этих метаклассов-кандидатов. Если ни один из метаклассов-кандидатов не соответствует этому критерию, то определение класса завершится ошибкой с TypeError
.
3.3.3.4. Подготовка пространства имен класса¶
Как только соответствующий метакласс будет идентифицирован, будет подготовлено пространство имен класса. Если метакласс имеет атрибут __prepare__
, он вызывается как namespace = metaclass.__prepare__(name, bases, **kwds)
(где дополнительные аргументы ключевого слова, если таковые имеются, берутся из определения класса). Метод __prepare__
должен быть реализован как classmethod
. Пространство имен, возвращаемое __prepare__
, передается в __new__
, но при создании конечного объекта класса пространство имен копируется в новый dict
.
Если у метакласса нет атрибута __prepare__
, то пространство имен класса инициализируется как пустое упорядоченное отображение.
См.также
- PEP 3115 - Метаклассы в Python 3000
Введен хук пространства имен
__prepare__
3.3.3.5. Выполнение тела класса¶
Тело класса выполняется (приблизительно) как exec(body, globals(), namespace)
. Ключевое отличие от обычного вызова exec()
заключается в том, что лексическая область видимости позволяет телу класса (включая любые методы) ссылаться на имена из текущей и внешней областей видимости, когда определение класса происходит внутри функции.
Однако, даже когда определение класса происходит внутри функции, методы, определенные внутри класса, по-прежнему не могут видеть имена, определенные в области действия класса. Доступ к переменным класса должен осуществляться через первый параметр метода экземпляра или класса или через неявную ссылку с лексической областью действия __class__
, описанную в следующем разделе.
3.3.3.6. Создание объекта класса¶
Как только пространство имен класса заполнено путем выполнения тела класса, объект класса создается путем вызова metaclass(name, bases, namespace, **kwds)
(дополнительные ключевые слова, передаваемые здесь, такие же, как и в __prepare__
).
Именно на этот объект класса будет ссылаться форма с нулевым аргументом super()
. __class__
это неявная ссылка на замыкание, создаваемая компилятором, если какие-либо методы в теле класса ссылаются либо на __class__
, либо на super
. Это позволяет форме с нулевым аргументом super()
корректно идентифицировать определяемый класс на основе лексической области видимости, в то время как класс или экземпляр, который использовался для выполнения текущего вызова, идентифицируется на основе первого аргумента, переданного методу.
Детали реализации CPython: В CPython 3.6 и более поздних версиях ячейка __class__
передается в метакласс как запись __classcell__
в пространстве имен класса. Если это присутствует, это должно быть распространено вплоть до вызова type.__new__
, чтобы класс был инициализирован правильно. Невыполнение этого требования приведет к появлению RuntimeError
в Python 3.8.
При использовании метакласса по умолчанию type
или любого другого метакласса, который в конечном итоге вызывает type.__new__
, после создания объекта class выполняются следующие дополнительные шаги настройки:
Метод
type.__new__
собирает все атрибуты в пространстве имен класса, которые определяют метод__set_name__()
;Эти методы
__set_name__
вызываются с определением класса и присвоением имени этому конкретному атрибуту;Перехватчик
__init_subclass__()
вызывается для непосредственного родительского класса нового класса в порядке разрешения его метода.
После создания объекта class он передается декораторам класса, включенным в определение класса (если таковые имеются), и результирующий объект привязывается к локальному пространству имен как определенный класс.
Когда с помощью type.__new__
создается новый класс, объект, указанный в качестве параметра пространства имен, копируется в новое упорядоченное отображение, а исходный объект отбрасывается. Новая копия помещается в прокси-сервер, доступный только для чтения, который становится атрибутом __dict__
объекта class.
См.также
- PEP 3135 - Новый супер
Описывает неявную ссылку на замыкание
__class__
3.3.3.7. Использование для метаклассов¶
Возможности использования метаклассов безграничны. Некоторые из рассмотренных идей включают перечисление, ведение журнала, проверку интерфейса, автоматическое делегирование, автоматическое создание свойств, прокси-серверы, фреймворки и автоматическую блокировку/синхронизацию ресурсов.
3.3.4. Настройка проверок экземпляров и подклассов¶
Следующие методы используются для переопределения поведения встроенных функций isinstance()
и issubclass()
по умолчанию.
В частности, метакласс abc.ABCMeta
реализует эти методы для того, чтобы разрешить добавление абстрактных базовых классов (ABC) в качестве «виртуальных базовых классов» к любому классу или типу (включая встроенные типы), включая другие ABC.
- class.__instancecheck__(self, instance)¶
Возвращает значение true, если instance следует считать (прямым или косвенным) экземпляром class. Если определено, вызывается для реализации
isinstance(instance, class)
.
- class.__subclasscheck__(self, subclass)¶
Возвращает значение true, если subclass следует считать (прямым или косвенным) подклассом class. Если он определен, вызывается для реализации
issubclass(subclass, class)
.
Обратите внимание, что эти методы рассматриваются в соответствии с типом (метаклассом) класса. Они не могут быть определены как методы класса в реальном классе. Это согласуется с поиском специальных методов, которые вызываются в экземплярах, только в этом случае экземпляр сам является классом.
См.также
- PEP 3119 - Представляем абстрактные базовые классы
Включает спецификацию для настройки поведения
isinstance()
иissubclass()
с помощью__instancecheck__()
и__subclasscheck__()
, с мотивацией для этой функциональности в контексте добавления абстрактных базовых классов (см.abc
модуль) на язык.
3.3.5. Эмуляция универсальных типов¶
При использовании type annotations часто бывает полезно параметризовать значение generic type, используя обозначение в квадратных скобках в Python. Например, аннотация list[int]
может использоваться для обозначения list
, в которой все элементы имеют тип int
.
См.также
- PEP 484 - Введите подсказки
Представляем фреймворк Python для аннотаций типов
- Generic Alias Types
Документация для объектов, представляющих параметризованные универсальные классы
- Дженерики, user-defined generics и
typing.Generic
Документация о том, как реализовать универсальные классы, которые могут быть параметризованы во время выполнения и поняты средствами статической проверки типов.
Класс, как правило, может быть параметризован только в том случае, если он определяет специальный метод класса __class_getitem__()
.
- classmethod object.__class_getitem__(cls, key)¶
Возвращает объект, представляющий специализацию универсального класса, с помощью аргументов типа, найденных в key.
Когда он определен в классе,
__class_getitem__()
автоматически становится методом класса. Таким образом, нет необходимости оформлять его как@classmethod
, когда он определен.
3.3.5.1. Цель создания __class_getitem__¶
Цель __class_getitem__()
- разрешить параметризацию универсальных классов стандартной библиотеки во время выполнения, чтобы упростить применение type hints к этим классам.
Чтобы реализовать пользовательские универсальные классы, которые могут быть параметризованы во время выполнения и поняты средствами статической проверки типов, пользователи должны либо наследовать от стандартного библиотечного класса, который уже реализует __class_getitem__()
, либо наследовать от typing.Generic
, который имеет свою собственную реализацию __class_getitem__()
.
Пользовательские реализации __class_getitem__()
для классов, определенных вне стандартной библиотеки, могут быть непонятны сторонним средствам проверки типов, таким как mypy. Использование __class_getitem__()
в любом классе для целей, отличных от указания типа, не рекомендуется.
3.3.5.2. __класс_getitem__ против __getitem__¶
Обычно subscription объекта, заключенного в квадратные скобки, вызывает метод экземпляра __getitem__()
, определенный в классе объекта. Однако, если подписываемый объект сам по себе является классом, вместо этого может быть вызван метод class __class_getitem__()
. __class_getitem__()
должен возвращать объект GenericAlias, если он правильно определен.
Представлен с помощью expression obj[x]
, интерпретатор Python выполняет что-то вроде следующего процесса, чтобы решить, следует ли вызывать __getitem__()
или __class_getitem__()
:
from inspect import isclass
def subscribe(obj, x):
"""Return the result of the expression 'obj[x]'"""
class_of_obj = type(obj)
# If the class of obj defines __getitem__,
# call class_of_obj.__getitem__(obj, x)
if hasattr(class_of_obj, '__getitem__'):
return class_of_obj.__getitem__(obj, x)
# Else, if obj is a class and defines __class_getitem__,
# call obj.__class_getitem__(x)
elif isclass(obj) and hasattr(obj, '__class_getitem__'):
return obj.__class_getitem__(x)
# Else, raise an exception
else:
raise TypeError(
f"'{class_of_obj.__name__}' object is not subscriptable"
)
В Python все классы сами по себе являются экземплярами других классов. Класс класса известен как metaclass этого класса, и большинство классов имеют класс type
в качестве своего метакласса. type
не определяет __getitem__()
, что означает, что такие выражения, как list[int]
, dict[str, float]
и tuple[str, bytes]
все это приводит к вызову __class_getitem__()
:
>>> # list has class "type" as its metaclass, like most classes:
>>> type(list)
<class 'type'>
>>> type(dict) == type(list) == type(tuple) == type(str) == type(bytes)
True
>>> # "list[int]" calls "list.__class_getitem__(int)"
>>> list[int]
list[int]
>>> # list.__class_getitem__ returns a GenericAlias object:
>>> type(list[int])
<class 'types.GenericAlias'>
Однако, если у класса есть пользовательский метакласс, который определяет __getitem__()
, подписка на класс может привести к другому поведению. Пример этого можно найти в модуле enum
:
>>> from enum import Enum
>>> class Menu(Enum):
... """A breakfast menu"""
... SPAM = 'spam'
... BACON = 'bacon'
...
>>> # Enum classes have a custom metaclass:
>>> type(Menu)
<class 'enum.EnumMeta'>
>>> # EnumMeta defines __getitem__,
>>> # so __class_getitem__ is not called,
>>> # and the result is not a GenericAlias object:
>>> Menu['SPAM']
<Menu.SPAM: 'spam'>
>>> type(Menu['SPAM'])
<enum 'Menu'>
См.также
- PEP 560 - Основная поддержка модуля ввода текста и универсальных типов
Вводим
__class_getitem__()
и описываем, когда subscription приводит к вызову__class_getitem__()
вместо__getitem__()
3.3.6. Эмуляция вызываемых объектов¶
- object.__call__(self[, args...])¶
Вызывается, когда экземпляр «вызывается» как функция; если этот метод определен,
x(arg1, arg2, ...)
примерно соответствуетtype(x).__call__(x, arg1, ...)
.
3.3.7. Имитация типов контейнеров¶
Для реализации объектов-контейнеров могут быть определены следующие методы. Контейнерами обычно являются sequences (например, lists
или tuples
) или mappings (например, dictionaries
), но могут представлять и другие контейнеры. Первый набор методов используется либо для эмуляции последовательности, либо для эмуляции отображения; разница в том, что для последовательности допустимыми ключами должны быть целые числа k, для которых 0 <= k < N
, где N - длина последовательности, или slice
объекты, которые определяют диапазон элементов. Также рекомендуется, чтобы сопоставления предоставляли методы keys()
, values()
, items()
, get()
, clear()
, setdefault()
, pop()
, popitem()
, copy()
, и update()
, которые ведут себя аналогично методам для стандартных объектов Python dictionary
. Модуль collections.abc
предоставляет MutableMapping
abstract base class, который помогает создавать эти методы из базового набора __getitem__()
, __setitem__()
, __delitem__()
, и keys()
. Изменяемые последовательности должны предоставлять методы append()
, count()
, index()
, extend()
, insert()
, pop()
, remove()
, reverse()
и sort()
, подобные стандартным объектам Python list
. Наконец, типы последовательностей должны реализовывать сложение (то есть объединение) и умножение (то есть повторение), определяя методы __add__()
, __radd__()
, __iadd__()
, __mul__()
, __rmul__()
и __imul__()
, описанные ниже; они не должны определять другие числовые операторы. Рекомендуется, чтобы как в отображениях, так и в последовательностях был реализован метод __contains__()
, позволяющий эффективно использовать оператор in
; для отображений in
следует выполнять поиск по ключам отображения; для последовательностей следует выполнять поиск по значениям. Кроме того, рекомендуется, чтобы как сопоставления, так и последовательности реализовывали метод __iter__()
, чтобы обеспечить эффективную итерацию по контейнеру; для сопоставлений __iter__()
следует выполнять итерацию по ключам объекта; для последовательностей следует выполнять итерацию по значениям.
- object.__len__(self)¶
Вызывается для реализации встроенной функции
len()
. Должен возвращать длину объекта, целое число>=
0. Кроме того, объект, который не определяет метод__bool__()
и метод__len__()
которого возвращает ноль, считается ложным в логическом контексте.Детали реализации CPython: В CPython длина должна быть не более
sys.maxsize
. Если длина больше, чемsys.maxsize
, некоторые функции (например,len()
) могут вызыватьOverflowError
. Чтобы предотвратить получениеOverflowError
при проверке истинности значения, объект должен определить метод__bool__()
.
- object.__length_hint__(self)¶
Вызывается для реализации
operator.length_hint()
. Должен возвращать приблизительную длину объекта (которая может быть больше или меньше фактической длины). Длина должна быть целым числом>=
0. Возвращаемое значение также может бытьNotImplemented
, которое обрабатывается так же, как если бы метода__length_hint__
вообще не существовало. Этот метод является чисто оптимизационным и никогда не требуется для корректности.Добавлено в версии 3.4.
Примечание
Нарезка выполняется исключительно с помощью следующих трех методов. Вызов типа
a[1:2] = b
переводится на
a[slice(1, 2, None)] = b
и так далее. Пропущенные элементы среза всегда заполняются None
.
- object.__getitem__(self, key)¶
Вызывается для реализации вычисления
self[key]
. Для типов sequence допустимыми ключами должны быть целые числа. Необязательно, они также могут поддерживать объектыslice
. Поддержка отрицательного индекса также необязательна. Если key имеет неподходящий тип, может быть поднято значениеTypeError
; если key является значением вне набора индексов для последовательности (после какой-либо специальной интерпретации отрицательных значений), должно быть поднято значениеIndexError
. Для типов mapping, если ключ отсутствует (не в контейнере), должен быть поднятKeyError
.Примечание
for
циклы ожидают, что для недопустимых индексов будет поднятIndexError
, чтобы обеспечить правильное определение конца последовательности.Примечание
Когда subscripting a class, вместо
__getitem__()
может быть вызван специальный метод класса__class_getitem__()
. Более подробную информацию смотрите в __класс_getitem__ против __getitem__.
- object.__setitem__(self, key, value)¶
Вызывается для выполнения присваивания
self[key]
. То же примечание, что и для__getitem__()
. Это должно быть реализовано только для сопоставлений, если объекты поддерживают изменения значений ключей, или если можно добавлять новые ключи, или для последовательностей, если можно заменять элементы. Для неподходящих значений ключа должны быть созданы те же исключения, что и для метода__getitem__()
.
- object.__delitem__(self, key)¶
Вызывается для реализации удаления
self[key]
. То же примечание, что и для__getitem__()
. Это должно быть реализовано только для сопоставлений, если объекты поддерживают удаление ключей, или для последовательностей, если элементы могут быть удалены из последовательности. Для неправильных значений ключа должны быть созданы те же исключения, что и для метода__getitem__()
.
- object.__missing__(self, key)¶
Вызывается с помощью
dict
.__getitem__()
для реализацииself[key]
для подклассов dict, когда ключа нет в словаре.
- object.__iter__(self)¶
Этот метод вызывается, когда для контейнера требуется iterator. Этот метод должен возвращать новый объект-итератор, который может выполнять итерацию по всем объектам в контейнере. Для сопоставлений он должен выполнять итерацию по ключам контейнера.
- object.__reversed__(self)¶
Вызывается (если присутствует) встроенным модулем
reversed()
для реализации обратной итерации. Он должен возвращать новый объект-итератор, который выполняет итерацию по всем объектам в контейнере в обратном порядке.Если метод
__reversed__()
не предусмотрен, встроенная функцияreversed()
вернется к использованию протокола последовательности (__len__()
и__getitem__()
). Объекты, поддерживающие протокол последовательности, должны предоставлять__reversed__()
только в том случае, если они могут обеспечить реализацию, которая является более эффективной, чем та, которая предоставляетсяreversed()
.
Операторы проверки принадлежности (in
и not in
) обычно реализуются в виде итерации через контейнер. Однако объекты-контейнеры могут предоставить следующий специальный метод с более эффективной реализацией, который также не требует, чтобы объект был итерируемым.
- object.__contains__(self, item)¶
Вызывается для реализации операторов проверки принадлежности. Должен возвращать значение true, если item находится в self, в противном случае значение false. Для объектов сопоставления при этом следует учитывать ключи сопоставления, а не значения или пары ключ-элемент.
Для объектов, которые не определяют
__contains__()
, тест на принадлежность сначала выполняет итерацию с помощью__iter__()
, затем по старому протоколу итерации последовательности с помощью__getitem__()
, см. this section in the language reference.
3.3.8. Эмуляция числовых типов¶
Для эмуляции числовых объектов могут быть определены следующие методы. Методы, соответствующие операциям, которые не поддерживаются конкретным типом реализованных чисел (например, побитовые операции для нецелых чисел), следует оставить неопределенными.
- object.__add__(self, other)¶
- object.__sub__(self, other)¶
- object.__mul__(self, other)¶
- object.__matmul__(self, other)¶
- object.__truediv__(self, other)¶
- object.__floordiv__(self, other)¶
- object.__mod__(self, other)¶
- object.__divmod__(self, other)¶
- object.__pow__(self, other[, modulo])¶
- object.__lshift__(self, other)¶
- object.__rshift__(self, other)¶
- object.__and__(self, other)¶
- object.__xor__(self, other)¶
- object.__or__(self, other)¶
Эти методы вызываются для реализации двоичных арифметических операций (
+
,-
,*
,@
,/
,//
,%
,divmod()
,pow()
,**
,<<
,>>
,&
,^
,|
). Например, для вычисления выраженияx + y
, где x - это экземпляр класса, у которого есть метод__add__()
, вызывается методtype(x).__add__(x, y)
. Метод__divmod__()
должен быть эквивалентен использованию__floordiv__()
и__mod__()
; он не должен быть связан с__truediv__()
. Обратите внимание, что__pow__()
должен быть определен как принимающий необязательный третий аргумент, если должна поддерживаться троичная версия встроенной функцииpow()
.Если один из этих методов не поддерживает операцию с указанными аргументами, он должен возвращать
NotImplemented
.
- object.__radd__(self, other)¶
- object.__rsub__(self, other)¶
- object.__rmul__(self, other)¶
- object.__rmatmul__(self, other)¶
- object.__rtruediv__(self, other)¶
- object.__rfloordiv__(self, other)¶
- object.__rmod__(self, other)¶
- object.__rdivmod__(self, other)¶
- object.__rpow__(self, other[, modulo])¶
- object.__rlshift__(self, other)¶
- object.__rrshift__(self, other)¶
- object.__rand__(self, other)¶
- object.__rxor__(self, other)¶
- object.__ror__(self, other)¶
Эти методы вызываются для реализации двоичных арифметических операций (
+
,-
,*
,@
,/
,//
,%
,divmod()
,pow()
,**
,<<
,>>
,&
,^
,|
) с отраженными (замененными местами) операндами. Эти функции вызываются только в том случае, если левый операнд не поддерживает соответствующую операцию [3] и операнды имеют разные типы. [4] Например, для вычисления выраженияx - y
, где y - это экземпляр класса, у которого есть метод__rsub__()
,type(y).__rsub__(y, x)
вызывается, еслиtype(x).__sub__(x, y)
возвращаетNotImplemented
.Обратите внимание, что троичный
pow()
не будет пытаться вызвать__rpow__()
(правила приведения стали бы слишком сложными).Примечание
Если тип правого операнда является подклассом типа левого операнда и этот подкласс предоставляет другую реализацию отраженного метода для операции, этот метод будет вызван перед неотраженным методом левого операнда. Такое поведение позволяет подклассам переопределять операции своих предков.
- object.__iadd__(self, other)¶
- object.__isub__(self, other)¶
- object.__imul__(self, other)¶
- object.__imatmul__(self, other)¶
- object.__itruediv__(self, other)¶
- object.__ifloordiv__(self, other)¶
- object.__imod__(self, other)¶
- object.__ipow__(self, other[, modulo])¶
- object.__ilshift__(self, other)¶
- object.__irshift__(self, other)¶
- object.__iand__(self, other)¶
- object.__ixor__(self, other)¶
- object.__ior__(self, other)¶
Эти методы вызываются для реализации расширенных арифметических назначений (
+=
,-=
,*=
,@=
,/=
,//=
,%=
,**=
,<<=
,>>=
,&=
,^=
,|=
). Эти методы должны попытаться выполнить операцию на месте (изменив self) и вернуть результат (который может быть, но не обязательно должен быть self). Если конкретный метод не определен или если этот метод возвращаетNotImplemented
, расширенное назначение возвращается к обычным методам. Например, если x является экземпляром класса с методом__iadd__()
, тоx += y
эквивалентноx = x.__iadd__(y)
. Если__iadd__()
не существует или еслиx.__iadd__(y)
возвращаетNotImplemented
,x.__add__(y)
иy.__radd__(x)
учитываются, как и при вычисленииx + y
. В определенных ситуациях расширенное назначение может привести к непредвиденным ошибкам (см. Почему при сложении a_tuple[i] += [„item“] возникает исключение?), но на самом деле такое поведение является частью модели данных.
- object.__neg__(self)¶
- object.__pos__(self)¶
- object.__abs__(self)¶
- object.__invert__(self)¶
Вызывается для реализации унарных арифметических операций (
-
,+
,abs()
и~
).
- object.__complex__(self)¶
- object.__int__(self)¶
- object.__float__(self)¶
Вызывается для реализации встроенных функций
complex()
,int()
иfloat()
. Должен возвращать значение соответствующего типа.
- object.__index__(self)¶
Вызывается для реализации
operator.index()
и всякий раз, когда Python необходимо без потерь преобразовать числовой объект в целочисленный (например, при нарезке или во встроенных функцияхbin()
,hex()
иoct()
). Наличие этого метода указывает на то, что числовой объект относится к целочисленному типу. Должен возвращать целое число.Если
__int__()
,__float__()
и__complex__()
не определены, то соответствующие встроенные функцииint()
,float()
иcomplex()
возвращаются к__index__()
.
- object.__round__(self[, ndigits])¶
- object.__trunc__(self)¶
- object.__floor__(self)¶
- object.__ceil__(self)¶
Вызывается для реализации встроенных функций
round()
иmath
trunc()
,floor()
иceil()
. Если значение ndigits не передано в__round__()
, все эти методы должны возвращать значение объекта, усеченное доIntegral
(обычноint
).Встроенная функция
int()
возвращается к__trunc__()
, если не определены ни__int__()
, ни__index__()
.Изменено в версии 3.11: Делегирование
int()
в__trunc__()
не рекомендуется.
3.3.9. С помощью контекстных менеджеров заявлений¶
context manager - это объект, который определяет контекст времени выполнения, который должен быть установлен при выполнении инструкции with
. Диспетчер контекста обрабатывает вход в требуемый контекст времени выполнения и выход из него для выполнения блока кода. Контекстные менеджеры обычно вызываются с помощью инструкции with
(описанной в разделе Оператор with), но также могут использоваться путем прямого вызова их методов.
Типичные области применения контекстных менеджеров включают сохранение и восстановление различных видов глобального состояния, блокировку и разблокировку ресурсов, закрытие открытых файлов и т.д.
Дополнительные сведения о контекстных менеджерах см. в разделе Типы контекстных менеджеров.
- object.__enter__(self)¶
Введите контекст среды выполнения, связанный с этим объектом. Оператор
with
свяжет возвращаемое значение этого метода с целевыми объектами, указанными в предложенииas
инструкции, если таковые имеются.
- object.__exit__(self, exc_type, exc_value, traceback)¶
Выйдите из контекста среды выполнения, связанного с этим объектом. Параметры описывают исключение, вызвавшее запуск контекста. Если выход из контекста был выполнен без исключения, все три аргумента будут равны
None
.Если выдано исключение, и метод хочет подавить это исключение (т.е. предотвратить его распространение), он должен вернуть значение true. В противном случае исключение будет обработано обычным образом при выходе из этого метода.
Обратите внимание, что методы
__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 - Сопоставление структурных паттернов
Спецификация для оператора Python
match
.
3.3.11. Поиск по специальному методу¶
Для пользовательских классов корректная работа неявных вызовов специальных методов гарантируется только в том случае, если они определены в типе объекта, а не в словаре экземпляра объекта. Это является причиной того, что следующий код вызывает исключение:
>>> class C:
... pass
...
>>> c = C()
>>> c.__len__ = lambda: 5
>>> len(c)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type 'C' has no len()
Причина такого поведения кроется в ряде специальных методов, таких как __hash__()
и __repr__()
, которые реализуются всеми объектами, включая объекты типа. Если бы при неявном поиске этих методов использовался обычный процесс поиска, они завершились бы неудачей при вызове самого объекта типа:
>>> 1 .__hash__() == hash(1)
True
>>> int.__hash__() == hash(int)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: descriptor '__hash__' of 'int' object needs an argument
Неправильная попытка вызвать несвязанный метод класса таким образом иногда называется «путаницей в метаклассах», и ее можно избежать, обходя экземпляр при поиске специальных методов:
>>> type(1).__hash__(1) == hash(1)
True
>>> type(int).__hash__(int) == hash(int)
True
В дополнение к обходу любых атрибутов экземпляра в интересах корректности, неявный поиск по специальному методу обычно также обходит метод __getattribute__()
даже для метакласса объекта:
>>> class Meta(type):
... def __getattribute__(*args):
... print("Metaclass getattribute invoked")
... return type.__getattribute__(*args)
...
>>> class C(object, metaclass=Meta):
... def __len__(self):
... return 10
... def __getattribute__(*args):
... print("Class getattribute invoked")
... return object.__getattribute__(*args)
...
>>> c = C()
>>> c.__len__() # Explicit lookup via instance
Class getattribute invoked
10
>>> type(c).__len__(c) # Explicit lookup via type
Metaclass getattribute invoked
10
>>> len(c) # Implicit lookup
10
Обход механизма __getattribute__()
таким образом предоставляет значительные возможности для оптимизации скорости работы интерпретатора за счет некоторой гибкости в обработке специальных методов (специальный метод должен быть установлен для самого объекта класса, чтобы интерпретатор мог последовательно вызывать его).
3.4. Сопрограммы¶
3.4.1. Доступные объекты¶
Объект awaitable обычно реализует метод __await__()
. Доступны функции Coroutine objects, возвращаемые из async def
.
Примечание
Объекты generator iterator, возвращаемые генераторами, помеченными как types.coroutine()
, также доступны, но они не реализуют __await__()
.
- object.__await__(self)¶
Должен возвращать iterator. Должен использоваться для реализации объектов awaitable. Например,
asyncio.Future
реализует этот метод, чтобы он был совместим с выражениемawait
.
Добавлено в версии 3.5.
См.также
PEP 492 для получения дополнительной информации о доступных объектах.
3.4.2. Объекты сопрограммы¶
Coroutine objects являются объектами awaitable. Выполнением сопрограммы можно управлять, вызывая __await__()
и повторяя результат. Когда сопрограмма завершает выполнение и возвращает результат, итератор генерирует StopIteration
, а возвращаемое значение содержит атрибут исключения value
. Если сопрограмма генерирует исключение, оно передается итератором. Сопрограммы не должны напрямую вызывать необработанные исключения StopIteration
.
В сопрограммах также есть методы, перечисленные ниже, которые аналогичны методам генераторов (см. Методы генератора-итератора). Однако, в отличие от генераторов, сопрограммы напрямую не поддерживают итерацию.
Изменено в версии 3.5.2: Это RuntimeError
для ожидания в сопрограмме более одного раза.
- coroutine.send(value)¶
Запускает или возобновляет выполнение сопрограммы. Если значение равно
None
, это эквивалентно продвижению итератора, возвращаемого с помощью__await__()
. Если value не равноNone
, этот метод делегируется методуsend()
итератора, который вызвал приостановку работы сопрограммы. Результат (возвращаемое значение,StopIteration
или другое исключение) такой же, как и при повторении возвращаемого значения__await__()
, описанного выше.
- coroutine.throw(value)¶
- coroutine.throw(type[, value[, traceback]])
Вызывает указанное исключение в сопрограмме. Этот метод делегируется методу
throw()
итератора, который вызвал приостановку сопрограммы, если у него есть такой метод. В противном случае исключение генерируется в точке приостановки. Результат (возвращаемое значение,StopIteration
или другое исключение) такой же, как и при выполнении итерации по возвращаемому значению__await__()
, описанному выше. Если исключение не перехватывается сопрограммой, оно передается обратно вызывающей стороне.
- coroutine.close()¶
Приводит к самоочищению сопрограммы и завершению работы. Если сопрограмма приостановлена, этот метод сначала делегируется методу
close()
итератора, который вызвал приостановку сопрограммы, если у него есть такой метод. Затем в точке приостановки запускаетсяGeneratorExit
, что приводит к немедленной очистке сопрограммы. Наконец, сопрограмма помечается как завершившая выполнение, даже если она никогда не запускалась.Объекты сопрограммы автоматически закрываются с помощью описанного выше процесса, когда они собираются быть уничтоженными.
3.4.3. Асинхронные итераторы¶
Асинхронный итератор может вызывать асинхронный код в своем методе __anext__
.
Асинхронные итераторы могут использоваться в операторе async for
.
- object.__aiter__(self)¶
Должен возвращать объект асинхронного итератора.
- object.__anext__(self)¶
Должен возвращать значение ожидаемое, приводящее к следующему значению итератора. По окончании итерации должна возникнуть ошибка
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__()
мог возвращать значение ожидаемое, которое преобразовалось бы в asynchronous iterator.
Начиная с Python 3.7, __aiter__()
должен возвращать объект асинхронного итератора. Возврат чего-либо еще приведет к ошибке TypeError
.
3.4.4. Асинхронные контекстные менеджеры¶
Асинхронный контекстный менеджер - это контекстный менеджер, который может приостановить выполнение с помощью своих методов __aenter__
и __aexit__
.
Асинхронные контекстные менеджеры могут использоваться в инструкции async with
.
- object.__aenter__(self)¶
Семантически аналогично
__enter__()
, с той лишь разницей, что он должен возвращать ожидаемый.
- object.__aexit__(self, exc_type, exc_value, traceback)¶
Семантически аналогично
__exit__()
, с той лишь разницей, что он должен возвращать ожидаемый.
Пример класса асинхронного контекстного менеджера:
class AsyncContextManager:
async def __aenter__(self):
await log('entering context')
async def __aexit__(self, exc_type, exc, tb):
await log('exiting context')
Добавлено в версии 3.5.
Сноски