3. Модель данных¶
3.1. Объекты, значения и типы¶
Objects - это абстракция Python для данных. Все данные в программе на Python представлены объектами или отношениями между объектами. (В некотором смысле, в соответствии с моделью фон Неймана о «компьютере с хранимыми программами», код также представлен объектами).
У каждого объекта есть идентификатор, тип и значение. Идентичность объекта никогда не меняется после его создания; вы можете считать ее адресом объекта в памяти. Оператор is
сравнивает идентичность двух объектов; функция id()
возвращает целое число, представляющее его идентичность.
Детали реализации CPython: Для CPython id(x)
- это адрес памяти, в которой хранится x
.
Тип объекта определяет операции, которые он поддерживает (например, «имеет ли он длину?»), а также определяет возможные значения для объектов этого типа. Функция type()
возвращает тип объекта (который сам является объектом). Как и его идентичность, type объекта также неизменна. [1]
Значение некоторых объектов может меняться. Объекты, значение которых может изменяться, называются изменяемыми; объекты, значение которых не изменяется после их создания, называются неизменяемыми. (Значение неизменяемого объекта-контейнера, содержащего ссылку на мутабельный объект, может измениться при изменении значения последнего; однако контейнер все равно считается неизменяемым, поскольку коллекция объектов, которую он содержит, не может быть изменена. Таким образом, неизменяемость - это не совсем то же самое, что неизменяемое значение, это более тонкий момент). Мутабельность объекта определяется его типом; например, числа, строки и кортежи являются неизменяемыми, а словари и списки - мутабельными.
Объекты никогда не уничтожаются явно; однако, когда они становятся недоступными, они могут быть собраны в мусор. Реализация может отложить сборку мусора или вовсе отказаться от нее - это вопрос качества реализации, как будет реализована сборка мусора, если не будут собраны объекты, до которых еще можно добраться.
Детали реализации CPython: В настоящее время CPython использует схему подсчета ссылок с (необязательным) отложенным обнаружением циклически связанного мусора, которая собирает большинство объектов, как только они становятся недостижимыми, но не гарантирует сбор мусора, содержащего циклические ссылки. Информацию об управлении сбором циклического мусора см. в документации к модулю gc
. Другие реализации действуют иначе, и CPython может измениться. Не полагайтесь на немедленную финализацию объектов, когда они становятся недоступными (поэтому всегда закрывайте файлы явно).
Обратите внимание, что использование средств трассировки или отладки реализации может оставить в живых объекты, которые обычно можно было бы собрать. Также обратите внимание, что перехват исключения с помощью оператора try
…except
может сохранить объекты живыми.
Некоторые объекты содержат ссылки на «внешние» ресурсы, такие как открытые файлы или окна. Подразумевается, что эти ресурсы освобождаются при сборке мусора, но поскольку сборка мусора не гарантирована, такие объекты также предоставляют явный способ освобождения внешнего ресурса, обычно метод close()
. Программам настоятельно рекомендуется явно закрывать такие объекты. Утверждение try
…finally
и утверждение with
предоставляют удобные способы сделать это.
Некоторые объекты содержат ссылки на другие объекты; они называются контейнерами. Примерами контейнеров являются кортежи, списки и словари. Ссылки являются частью значения контейнера. В большинстве случаев, когда мы говорим о значении контейнера, мы подразумеваем значения, а не идентификаторы содержащихся в нем объектов; однако, когда мы говорим о изменяемости контейнера, подразумеваются только идентификаторы непосредственно содержащихся в нем объектов. Так, если неизменяемый контейнер (например, кортеж) содержит ссылку на изменяемый объект, его значение изменится при изменении этого изменяемого объекта.
Типы влияют практически на все аспекты поведения объектов. Даже важность идентичности объектов в некотором смысле затрагивается: для неизменяемых типов операции, вычисляющие новые значения, могут фактически возвращать ссылку на любой существующий объект с тем же типом и значением, в то время как для изменяемых объектов это недопустимо. Например, после a = 1; b = 1
, a
и b
могут ссылаться или не ссылаться на один и тот же объект со значением one, в зависимости от реализации, но после c = []; d = []
, c
и d
гарантированно ссылаются на два разных, уникальных, вновь созданных пустых списка. (Обратите внимание, что c = d = []
присваивает один и тот же объект и c
, и d
).
3.2. Стандартная иерархия типов¶
Ниже приведен список типов, встроенных в Python. Модули расширения (написанные на C, Java или других языках, в зависимости от реализации) могут определять дополнительные типы. Будущие версии Python могут добавить типы в иерархию типов (например, рациональные числа, эффективно хранимые массивы целых чисел и т. д.), хотя такие дополнения часто будут предоставляться через стандартную библиотеку.
Некоторые из приведенных ниже описаний типов содержат параграф, в котором перечислены «специальные атрибуты». Это атрибуты, которые предоставляют доступ к реализации и не предназначены для общего использования. Их определение может измениться в будущем.
3.2.1. Нет¶
Этот тип имеет единственное значение. Существует единственный объект с этим значением. Доступ к этому объекту осуществляется через встроенное имя None
. Он используется для обозначения отсутствия значения во многих ситуациях, например, возвращается из функций, которые явно ничего не возвращают. Его истинностное значение - false.
3.2.2. NotImplemented¶
Этот тип имеет единственное значение. Существует единственный объект с этим значением. Доступ к этому объекту осуществляется через встроенное имя NotImplemented
. Числовые методы и методы сравнения должны возвращать это значение, если они не реализуют операцию для предоставленных операндов. (Тогда интерпретатор попробует отраженную операцию или другой запасной вариант, в зависимости от оператора). Это значение не должно оцениваться в контексте булевых значений.
Более подробную информацию см. в разделе Реализация арифметических операций.
Изменено в версии 3.9: Оценка NotImplemented
в булевом контексте была устаревшей.
Изменено в версии 3.14: Оценка NotImplemented
в булевом контексте теперь выводит TypeError
. Ранее, начиная с Python 3.9, она оценивалась в True
и выдавала DeprecationWarning
.
3.2.3. Эллипсис¶
Этот тип имеет единственное значение. Существует единственный объект с этим значением. Доступ к этому объекту осуществляется через литерал ...
или встроенное имя Ellipsis
. Его истинностное значение - true.
3.2.4. numbers.Number
¶
Они создаются с помощью числовых литералов и возвращаются как результаты арифметических операторов и встроенных арифметических функций. Числовые объекты неизменяемы; после создания их значение никогда не меняется. Числа Python, конечно, тесно связаны с математическими числами, но с учетом ограничений, накладываемых на числовое представление в компьютерах.
Строковые представления числовых классов, вычисляемые через __repr__()
и __str__()
, обладают следующими свойствами:
Они представляют собой допустимые числовые литералы, которые при передаче в конструктор своего класса создают объект, имеющий значение исходного числа.
По возможности, представление ведется по основанию 10.
Ведущие нули, возможно, за исключением одного нуля перед десятичной точкой, не отображаются.
Нули в конце строки, возможно, за исключением одного нуля после десятичной точки, не отображаются.
Знак ставится только в том случае, если число отрицательное.
Python различает целые числа, числа с плавающей точкой и комплексные числа:
3.2.4.1. numbers.Integral
¶
Они представляют собой элементы из математического набора целых чисел (положительных и отрицательных).
Примечание
Правила представления целых чисел предназначены для наиболее осмысленной интерпретации операций сдвига и маскирования отрицательных целых чисел.
Существует два типа целых чисел:
- Целые числа (
int
) Они представляют числа в неограниченном диапазоне, ограниченные только доступной (виртуальной) памятью. Для операций сдвига и маскирования предполагается двоичное представление, а отрицательные числа представляются в варианте 2’s complement, который создает иллюзию бесконечной строки знаковых битов, простирающейся влево.
- Булевы (
bool
) Они представляют истинностные значения False и True. Два объекта, представляющие значения
False
иTrue
, являются единственными булевыми объектами. Тип Boolean является подтипом типа integer, и булевы значения ведут себя как значения 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. При использовании в качестве выражения срез - это последовательность того же типа. Замечание выше об отрицательных индексах также относится к отрицательным позициям срезов.
Некоторые последовательности также поддерживают «расширенную нарезку» с третьим параметром «шаг»: a[i:j:k]
выбирает все элементы a с индексом x, где x = i + n*k
, n >=
0
и i <=
x <
j.
Последовательности различаются в зависимости от их изменяемости:
3.2.5.1. Неизменяемые последовательности¶
Объект неизменяемого типа последовательности не может измениться после его создания. (Если объект содержит ссылки на другие объекты, эти другие объекты могут быть мутабельными и могут быть изменены; однако коллекция объектов, на которые непосредственно ссылается неизменяемый объект, не может измениться).
Следующие типы являются неизменяемыми последовательностями:
- Струны
Строка - это последовательность значений, представляющих кодовые точки Unicode. Все кодовые точки в диапазоне
U+0000 - U+10FFFF
могут быть представлены в строке. В Python нет типа char; вместо этого каждая кодовая точка в строке представляется как строковый объект длиной1
. Встроенная функцияord()
преобразует кодовую точку из ее строковой формы в целое число в диапазоне0 - 10FFFF
;chr()
преобразует целое число в диапазоне0 - 10FFFF
в строковый объект соответствующей длины1
.str.encode()
может использоваться для преобразованияstr
вbytes
с использованием заданной текстовой кодировки, аbytes.decode()
- для достижения обратного результата.- Кортежи
Элементы кортежа - это произвольные объекты Python. Кортежи из двух или более элементов формируются из списков выражений, разделенных запятыми. Кортеж из одного элемента («синглтон») может быть сформирован путем присоединения запятой к выражению (выражение само по себе не создает кортеж, поскольку скобки должны использоваться для группировки выражений). Пустой кортеж может быть образован пустой парой круглых скобок.
- Байты
Объект bytes - это неизменяемый массив. Элементами являются 8-битные байты, представленные целыми числами в диапазоне 0 <= x < 256. Для создания байтовых объектов можно использовать литералы байтов (например,
b'abc'
) и встроенный конструкторbytes()
. Кроме того, объекты bytes можно декодировать в строки с помощью методаdecode()
.
3.2.5.2. Мутирующие последовательности¶
Изменчивые последовательности могут быть изменены после их создания. Нотации подписки и нарезки могут использоваться в качестве цели операторов присваивания и del
(удаления).
Примечание
Модуль collections
и array
представляют собой дополнительные примеры изменяемых типов последовательностей.
В настоящее время существует два внутренних изменяемых типа последовательностей:
- Списки
Элементы списка - это произвольные объекты Python. Списки формируются путем помещения списка выражений, разделенных запятыми, в квадратные скобки. (Обратите внимание, что для формирования списков длиной 0 или 1 не требуется никаких специальных случаев).
- Массивы байтов
Объект bytearray - это изменяемый массив. Они создаются с помощью встроенного конструктора
bytearray()
. Помимо того, что байтовые массивы являются мутабельными (и, следовательно, нехешируемыми), в остальном они предоставляют тот же интерфейс и функциональность, что и неизменяемые объектыbytes
.
3.2.6. Типы наборов¶
Они представляют собой неупорядоченные, конечные наборы уникальных, неизменяемых объектов. Как таковые, они не могут быть проиндексированы никаким подскриптом. Однако их можно итерировать, а встроенная функция len()
возвращает количество элементов в наборе. Обычно множества используются для быстрой проверки принадлежности, удаления дубликатов из последовательности и вычисления математических операций, таких как пересечение, объединение, разность и симметричная разность.
Для элементов множества действуют те же правила неизменяемости, что и для ключей словаря. Обратите внимание, что числовые типы подчиняются обычным правилам числового сравнения: если два числа сравниваются одинаково (например, 1
и 1.0
), только одно из них может содержаться в наборе.
В настоящее время существует два типа встроенных наборов:
- Наборы
Они представляют собой изменяемое множество. Они создаются встроенным конструктором
set()
и могут быть изменены впоследствии несколькими методами, напримерadd()
.- Замороженные декорации
Они представляют собой неизменяемое множество. Они создаются с помощью встроенного конструктора
frozenset()
. Поскольку фростенсет неизменяем и hashable, он может быть использован как элемент другого множества или как ключ словаря.
3.2.7. Отображения¶
Они представляют собой конечные наборы объектов, индексируемых произвольными наборами индексов. Условное обозначение a[k]
выбирает из отображения a
элемент, индексируемый k
; его можно использовать в выражениях и в качестве цели присваиваний или операторов 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. Специальные атрибуты, доступные только для чтения¶
Атрибут |
Значение |
---|---|
|
Ссылка на |
|
Объект ячейки имеет атрибут |
3.2.8.1.2. Специальные атрибуты, доступные для записи¶
Большинство этих атрибутов проверяют тип присвоенного значения:
Атрибут |
Значение |
---|---|
|
Строка документации функции, или |
|
Имя функции. См. также: |
|
Функция qualified name. См. также: Added in version 3.3. |
|
Имя модуля, в котором была определена функция, или |
|
Значение |
|
code object, представляющий скомпилированное тело функции. |
|
Пространство имен, поддерживающее произвольные атрибуты функций. См. также: |
|
Словарь |
|
|
|
Added in version 3.12. |
Объекты функций также поддерживают получение и установку произвольных атрибутов, которые могут быть использованы, например, для прикрепления метаданных к функциям. Для получения и установки таких атрибутов используется обычная атрибутивная точка-нотация.
Детали реализации CPython: Текущая реализация CPython поддерживает атрибуты функций только для функций, определяемых пользователем. Атрибуты функций для built-in functions могут быть поддержаны в будущем.
Дополнительная информация об определении функции может быть получена из ее code object (доступной через атрибут __code__
).
3.2.8.2. Методы экземпляра¶
Объект метода экземпляра объединяет класс, экземпляр класса и любой вызываемый объект (обычно пользовательскую функцию).
Специальные атрибуты, доступные только для чтения:
|
Указывает на объект экземпляра класса, к которому применяется метод bound. |
|
Относится к исходному function object. |
|
Документация метода (такая же, как |
|
Имя метода (такое же, как |
|
Имя модуля, в котором был определен метод, или |
Методы также поддерживают доступ (но не установку) к атрибутам произвольной функции на базовом function object.
Определенные пользователем объекты методов могут быть созданы при получении атрибута класса (возможно, через экземпляр этого класса), если этот атрибут является определенным пользователем объектом function object или classmethod
.
Когда объект метода экземпляра создается путем извлечения определенного пользователем function object из класса через один из его экземпляров, его атрибутом __self__
является экземпляр, а объект метода, как говорят, связан. Атрибутом __func__
нового метода является исходный объект функции.
Когда объект метода экземпляра создается путем извлечения объекта classmethod
из класса или экземпляра, его атрибутом __self__
является сам класс, а атрибутом __func__
- объект функции, лежащий в основе метода класса.
Когда вызывается объект метода экземпляра, вызывается базовая функция (__func__
), вставляя экземпляр класса (__self__
) перед списком аргументов. Например, если C
- класс, содержащий определение функции f()
, а x
- экземпляр C
, вызов x.f(1)
эквивалентен вызову C.f(x, 1)
.
Когда объект метода экземпляра является производным от объекта classmethod
, «экземпляр класса», хранящийся в __self__
, на самом деле является самим классом, так что вызов x.f(1)
или C.f(1)
эквивалентен вызову f(C,1)
, где f
является базовой функцией.
Обратите внимание, что преобразование из 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 - это объект списка. В этом случае для объекта, обозначенного alist, устанавливается специальный атрибут __self__
, доступный только для чтения. (Атрибут имеет ту же семантику, что и в случае с 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__()
. Объект модуля имеет пространство имен, реализуемое объектом dictionary
(это словарь, на который ссылается атрибут __globals__
функций, определенных в модуле). Ссылки на атрибуты переводятся в поиск в этом словаре, например, m.x
эквивалентен m.__dict__["x"]
. Объект модуля не содержит объект кода, используемый для инициализации модуля (поскольку после инициализации он не нужен).
Присвоение атрибутов обновляет словарь пространств имен модуля, например, m.x = 1
эквивалентно m.__dict__["x"] = 1
.
Предопределенные (записываемые) атрибуты:
__name__
Имя модуля.
__doc__
Строка документации модуля, или
None
, если она недоступна.__file__
Имя пути к файлу, из которого был загружен модуль, если он был загружен из файла. Атрибут
__file__
может отсутствовать для некоторых типов модулей, например модулей на языке C, статически подключаемых к интерпретатору. Для модулей расширения, загружаемых динамически из общей библиотеки, это имя пути к файлу общей библиотеки.__annotations__
Словарь, содержащий variable annotations, собранные во время выполнения тела модуля. О лучших практиках работы с
__annotations__
читайте в разделе Лучшие практики использования аннотаций.
Специальный атрибут, доступный только для чтения: __dict__
- пространство имен модуля в виде словарного объекта.
Детали реализации CPython: Из-за того, как CPython очищает словари модулей, словарь модуля будет очищен, когда модуль выйдет из области видимости, даже если в словаре останутся живые ссылки. Чтобы избежать этого, скопируйте словарь или держите модуль рядом, используя его словарь напрямую.
3.2.10. Пользовательские классы¶
Пользовательские типы классов обычно создаются в определениях классов (см. раздел Определения классов). Класс имеет пространство имен, реализованное в виде объекта-словаря. Ссылки на атрибуты класса переводятся в поиск в этом словаре, например, C.x
переводится в C.__dict__["x"]
(хотя существует ряд крючков, позволяющих использовать другие способы поиска атрибутов). Если имя атрибута не найдено, поиск атрибута продолжается в базовых классах. Этот поиск в базовых классах использует порядок разрешения методов C3, который ведет себя корректно даже при наличии «ромбовидных» структур наследования, когда существует несколько путей наследования, ведущих к общему предку. Дополнительные подробности о C3 MRO, используемом в Python, можно найти в Порядок разрешения методов в Python 2.3.
Когда ссылка на атрибут класса (скажем, для класса C
) дает объект метода класса, она преобразуется в объект метода экземпляра, атрибутом __self__
которого является C
. Если в результате будет получен объект staticmethod
, он преобразуется в объект, обернутый статическим объектом метода. Еще один способ, с помощью которого атрибуты, получаемые из класса, могут отличаться от тех, которые на самом деле содержатся в его __dict__
, см. в разделе Реализация дескрипторов.
Назначения атрибутов класса обновляют словарь класса, но не словарь базового класса.
Объект класса может быть вызван (см. выше), чтобы получить экземпляр класса (см. ниже).
Специальные атрибуты:
__name__
Имя класса.
__module__
Имя модуля, в котором был определен класс.
__dict__
Словарь, содержащий пространство имен класса.
__bases__
Кортеж, содержащий базовые классы в порядке их появления в списке базовых классов.
__doc__
Строка документации класса, или
None
, если она не определена.__annotations__
Словарь, содержащий variable annotations, собранные во время выполнения тела класса. О лучших практиках работы с
__annotations__
читайте в разделе Лучшие практики использования аннотаций.__type_params__
Кортеж, содержащий type parameters из generic class.
__static_attributes__
Кортеж, содержащий имена атрибутов данного класса, доступ к которым осуществляется через
self.X
из любой функции в его теле.__firstlineno__
Номер строки первой строки определения класса, включая декораторы.
3.2.11. Экземпляры классов¶
Экземпляр класса создается путем вызова объекта класса (см. выше). У экземпляра класса есть пространство имен, реализованное в виде словаря, в котором в первую очередь ищутся ссылки на атрибуты. Если атрибут там не найден, а класс экземпляра имеет атрибут с таким именем, поиск продолжается в атрибутах класса. Если найден атрибут класса, являющийся объектом пользовательской функции, он преобразуется в объект метода экземпляра, атрибутом __self__
которого является экземпляр. Объекты статических методов и методов классов также преобразуются; см. выше в разделе «Классы». Еще один способ, с помощью которого атрибуты класса, получаемые через его экземпляры, могут отличаться от объектов, хранящихся в __dict__
класса, см. в разделе Реализация дескрипторов. Если атрибут класса не найден, а у класса объекта есть метод __getattr__()
, он вызывается для выполнения поиска.
Присвоение и удаление атрибутов обновляет словарь экземпляра, но не словарь класса. Если у класса есть метод __setattr__()
или __delattr__()
, он вызывается вместо прямого обновления словаря экземпляра.
Экземпляры классов могут притворяться числами, последовательностями или отображениями, если у них есть методы с определенными специальными именами. См. раздел Специальные имена методов.
Специальные атрибуты: __dict__
- словарь атрибутов; __class__
- класс экземпляра.
3.2.12. Объекты ввода/вывода (также известные как файловые объекты)¶
Символ file object означает открытый файл. Для создания файловых объектов доступны различные ярлыки: встроенная функция open()
, а также os.popen()
, os.fdopen()
и метод makefile()
объектов сокетов (и, возможно, другие функции или методы, предоставляемые модулями расширения).
Объекты sys.stdin
, sys.stdout
и sys.stderr
инициализируются файловыми объектами, соответствующими стандартным потокам ввода, вывода и ошибок интерпретатора; все они открыты в текстовом режиме и поэтому следуют интерфейсу, определенному абстрактным классом io.TextIOBase
.
3.2.13. Внутренние типы¶
Несколько типов, используемых интерпретатором внутри, открыты для пользователя. Их определения могут измениться в будущих версиях интерпретатора, но для полноты картины они упомянуты здесь.
3.2.13.1. Кодовые объекты¶
Объекты кода представляют собой байтно-компилированный исполняемый код Python, или bytecode. Разница между объектом кода и объектом функции заключается в том, что объект функции содержит явную ссылку на глобалы функции (модуль, в котором она была определена), а объект кода не содержит контекста; также значения аргументов по умолчанию хранятся в объекте функции, а не в объекте кода (поскольку они представляют собой значения, вычисляемые во время выполнения). В отличие от объектов функций, объекты кода неизменяемы и не содержат ссылок (прямых или косвенных) на изменяемые объекты.
3.2.13.1.1. Специальные атрибуты, доступные только для чтения¶
|
Имя функции |
|
Полное имя функции Added in version 3.11. |
|
Общее количество позиционных parameters (включая только позиционные параметры и параметры со значениями по умолчанию), которые имеет функция |
|
Количество только позиционных parameters (включая аргументы со значениями по умолчанию), которые имеет функция |
|
Количество аргументов parameters (включая аргументы со значениями по умолчанию), которые имеет функция. |
|
Количество local variables, используемых функцией (включая параметры) |
|
A |
|
|
|
A |
|
Строка, представляющая последовательность инструкций bytecode в функции |
|
|
|
|
|
Имя файла, из которого был скомпилирован код |
|
Номер строки первой строки функции |
|
Строка, кодирующая отображение смещений bytecode на номера строк. Подробности см. в исходном коде интерпретатора. Не рекомендуется, начиная с версии 3.12: Этот атрибут объектов кода устарел и может быть удален в Python 3.14. |
|
Требуемый размер стека объекта кода |
|
В |
Для 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 в объекте кода.
Итератор возвращает
tuple
, содержащие(start_line, end_line, start_column, end_column)
. Кортеж i-th соответствует позиции исходного кода, скомпилированного в единицу кода i-th. Информация в столбцах представляет собой 0-индексированные utf-8 смещения байтов в данной строке исходного кода.Эта позиционная информация может отсутствовать. Неполный список случаев, когда это может произойти:
Запуск интерпретатора с
-X
no_debug_ranges
.Загрузка pyc-файла, скомпилированного при использовании
-X
no_debug_ranges
.Кортежи позиций, соответствующие искусственным инструкциям.
Номера строк и столбцов, которые не могут быть представлены из-за ограничений конкретной реализации.
Когда это происходит, некоторые или все элементы кортежа могут быть
None
.Added in version 3.11.
Примечание
Эта возможность требует хранения позиций столбцов в объектах кода, что может привести к небольшому увеличению использования диска скомпилированных файлов Python или памяти интерпретатора. Чтобы избежать хранения дополнительной информации и/или отключить печать дополнительной информации о возвратах к трассировке, используйте флаг
-X
no_debug_ranges
флаг командной строки или переменная окруженияPYTHONNODEBUGRANGES
.
- codeobject.co_lines()¶
Возвращает итератор, содержащий информацию о последовательных диапазонах bytecode. Каждый полученный элемент представляет собой
(start, end, lineno)
tuple
:start
(символint
) представляет собой смещение (включительно) начала диапазона bytecode.end
(символint
) представляет собой смещение (исключительное) конца диапазона bytecode.lineno
- этоint
, представляющий номер строки в диапазоне bytecode, илиNone
, если байткоды в данном диапазоне не имеют номера строки
Полученные предметы будут обладать следующими свойствами:
Первый полученный диапазон будет иметь значение
start
, равное 0.Диапазоны
(start, end)
будут неубывающими и последовательными. То есть, для любой парыtuple
,start
второго будет равенend
первого.Никакой диапазон не будет обратным:
end >= start
для всех троек.Последний
tuple
, полученный в результате, будет иметьend
, равный размеру bytecode.
Допускаются диапазоны нулевой ширины, где
start == end
. Диапазоны нулевой ширины используются для строк, которые присутствуют в исходном коде, но были удалены компилятором bytecode.Added in version 3.10.
См.также
- PEP 626 - Точные номера строк для отладки и других инструментов.
PEP, в котором был введен метод
co_lines()
.
- codeobject.replace(**kwargs)¶
Возвращает копию объекта кода с новыми значениями для указанных полей.
Объекты кода также поддерживаются общей функцией
copy.replace()
.Added in version 3.8.
3.2.13.2. Каркасные объекты¶
Объекты Frame представляют кадры выполнения. Они могут встречаться в traceback objects, а также передаются в зарегистрированные функции трассировки.
3.2.13.2.1. Специальные атрибуты, доступные только для чтения¶
|
Указывает на предыдущий кадр стека (в сторону вызывающей стороны), или |
|
code object, выполняемый в этом кадре. Доступ к этому атрибуту вызывает auditing event |
|
Отображение, используемое кадром для поиска local variables. Если кадр ссылается на optimized scope, то может быть возвращен прокси-объект с возможностью записи. Изменено в версии 3.13: Возвращает прокси для оптимизированных диапазонов. |
|
Словарь, используемый фреймом для поиска global variables. |
|
Словарь, используемый фреймом для поиска built-in (intrinsic) names. |
|
«Точная инструкция» объекта кадра (это индекс в строке bytecode строки code object) |
3.2.13.2.2. Специальные атрибуты, доступные для записи¶
|
Если не |
|
Установите этот атрибут в значение |
|
Установите этот атрибут в |
|
Номер текущей строки кадра – запись в этот атрибут из функции трассировки переходит на указанную строку (только для самого нижнего кадра). Отладчик может реализовать команду Jump (она же Set Next Statement) путем записи в этот атрибут. |
3.2.13.2.3. Методы объекта фрейма¶
Объекты фрейма поддерживают один метод:
- frame.clear()¶
Этот метод очищает все ссылки на local variables, принадлежащие кадру. Также, если фрейм принадлежал generator, генератор завершается. Это помогает разорвать циклы ссылок с участием объектов фрейма (например, при перехвате exception и сохранении его traceback для последующего использования).
RuntimeError
поднимается, если кадр в данный момент выполняется или приостановлен.Added in version 3.4.
Изменено в версии 3.13: Попытка очистить приостановленный кадр приводит к появлению
RuntimeError
(как это всегда происходило с выполняющимися кадрами).
3.2.13.3. Объекты отслеживания¶
Объекты traceback представляют собой трассировку стека exception. Объект traceback неявно создается при возникновении исключения, а также может быть явно создан вызовом types.TracebackType
.
Изменено в версии 3.7: Объекты Traceback теперь можно явно инстанцировать из кода 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 или stride среза. Отсутствующие или выходящие за пределы индексы обрабатываются в соответствии с обычными срезами.
3.2.13.5. Объекты статических методов¶
Статические объекты методов позволяют преодолеть описанное выше преобразование объектов функций в объекты методов. Статический объект метода - это обертка вокруг любого другого объекта, обычно объекта метода, определяемого пользователем. Когда статический объект метода извлекается из класса или экземпляра класса, возвращаемым объектом является обернутый объект, который не подвергается никаким дальнейшим преобразованиям. Статические объекты методов также можно вызывать. Объекты статических методов создаются встроенным конструктором staticmethod()
.
3.2.13.6. Объекты методов класса¶
Объект метода класса, как и объект статического метода, представляет собой обертку вокруг другого объекта, которая изменяет способ получения этого объекта из классов и экземпляров классов. Поведение объектов методов классов при таком извлечении описано выше, в разделе «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).Типичные реализации создают новый экземпляр класса, вызывая метод
__new__()
суперкласса с помощьюsuper().__new__(cls[, ...])
с соответствующими аргументами, а затем модифицируют вновь созданный экземпляр по мере необходимости, прежде чем вернуть его.Если при конструировании объекта был вызван метод
__new__()
и он вернул экземпляр cls, то метод__init__()
нового экземпляра будет вызван как__init__(self[, ...])
, где self - новый экземпляр, а остальные аргументы те же, что были переданы конструктору объекта.Если
__new__()
не возвращает экземпляр cls, то метод__init__()
нового экземпляра не будет вызван.__new__()
предназначен в основном для того, чтобы позволить подклассам неизменяемых типов (таких как int, str или tuple) настраивать создание экземпляров. Он также часто переопределяется в пользовательских метаклассах для настройки создания классов.
- object.__init__(self[, ...])¶
Вызывается после создания экземпляра (по
__new__()
), но до его возврата вызывающему. Аргументами являются те, которые передаются в выражение конструктора класса. Если базовый класс имеет метод__init__()
, то метод__init__()
производного класса, если таковой имеется, должен явно вызывать его, чтобы обеспечить правильную инициализацию части экземпляра базового класса; например:super().__init__([args...])
.Поскольку
__new__()
и__init__()
работают вместе при конструировании объектов (__new__()
для создания и__init__()
для настройки),__init__()
не может возвращать значения, отличные отNone
; это приведет к возникновениюTypeError
во время выполнения.
- object.__del__(self)¶
Вызывается, когда экземпляр собирается быть уничтоженным. Его также называют финализатором или (неправильно) деструктором. Если у базового класса есть метод
__del__()
, то метод__del__()
производного класса, если таковой имеется, должен явно вызывать его, чтобы обеспечить правильное удаление части экземпляра базового класса.Метод
__del__()
может (хотя и не рекомендуется!) отложить уничтожение экземпляра, создав новую ссылку на него. Это называется воскрешением объекта. Вызывать ли метод__del__()
второй раз, когда воскрешенный объект собирается быть уничтоженным, зависит от реализации; текущая реализация CPython вызывает его только один раз.Не гарантируется, что методы
__del__()
будут вызваны для объектов, которые все еще существуют после выхода из интерпретатора.Примечание
del x
не вызывает напрямуюx.__del__()
— первая уменьшает счетчик ссылок дляx
на единицу, а вторая вызывается только тогда, когда счетчик ссылокx
достигает нуля.Детали реализации CPython: Цикл ссылок может препятствовать тому, чтобы счетчик ссылок объекта обнулился. В этом случае цикл будет позже обнаружен и удален с помощью cyclic garbage collector. Частой причиной циклов ссылок является ситуация, когда исключение было поймано в локальной переменной. Локальные переменные фрейма ссылаются на исключение, которое ссылается на свой собственный traceback, который ссылается на локальные переменные всех фреймов, попавших в traceback.
См.также
Документация для модуля
gc
.Предупреждение
Поскольку методы
__del__()
вызываются в небезопасных условиях, исключения, возникающие во время их выполнения, игнорируются, и вместо них вsys.stderr
выводится предупреждение. В частности:__del__()
может быть вызван при выполнении произвольного кода, в том числе из любого произвольного потока. Если__del__()
нужно взять блокировку или вызвать любой другой блокирующий ресурс, это может привести к тупику, так как ресурс может быть уже занят кодом, прерванным для выполнения__del__()
.__del__()
может быть выполнена во время завершения работы интерпретатора. Как следствие, глобальные переменные, к которым ему нужно получить доступ (в том числе в других модулях), могут быть уже удалены или установлены в значениеNone
. Python гарантирует, что глобальные переменные, имя которых начинается с одного подчеркивания, удаляются из своего модуля до удаления других глобальных переменных; если других ссылок на такие глобальные переменные не существует, это может помочь убедиться, что импортируемые модули все еще доступны на момент вызова метода__del__()
.
- object.__repr__(self)¶
Вызывается встроенной функцией
repr()
для вычисления «официального» строкового представления объекта. Если это вообще возможно, оно должно выглядеть как правильное выражение Python, которое можно использовать для воссоздания объекта с тем же значением (при соответствующем окружении). Если это невозможно, то должна быть возвращена строка вида<...some useful description...>
. Возвращаемое значение должно быть строковым объектом. Если класс определяет__repr__()
, но не__str__()
, то__repr__()
также используется, когда требуется «неформальное» строковое представление экземпляров этого класса.Обычно это используется для отладки, поэтому важно, чтобы представление было информационно насыщенным и однозначным.
- object.__str__(self)¶
Вызывается
str(object)
и встроенными функциямиformat()
иprint()
для вычисления «неформального» или хорошо печатаемого строкового представления объекта. Возвращаемое значение должно быть объектом string.Этот метод отличается от
object.__repr__()
тем, что не ожидается, что__str__()
вернет правильное выражение Python: можно использовать более удобное или краткое представление.Реализация по умолчанию, определяемая встроенным типом
object
, вызываетobject.__repr__()
.
- object.__bytes__(self)¶
Вызывается bytes для вычисления байт-строкового представления объекта. В результате должен быть возвращен объект
bytes
.
- object.__format__(self, format_spec)¶
Вызывается встроенной функцией
format()
и, соответственно, оценкой formatted string literals и методомstr.format()
для получения «отформатированного» строкового представления объекта. Аргумент format_spec представляет собой строку, содержащую описание желаемых параметров форматирования. Интерпретация аргумента format_spec зависит от типа, реализующего__format__()
, однако большинство классов либо делегируют форматирование одному из встроенных типов, либо используют схожий синтаксис опций форматирования.Описание стандартного синтаксиса форматирования см. в разделе Мини-язык спецификации формата.
Возвращаемое значение должно быть строковым объектом.
Изменено в версии 3.4: Метод __format__ из
object
сам по себе вызывает ошибкуTypeError
, если ему передается любая непустая строка.Изменено в версии 3.7:
object.__format__(x, '')
теперь эквивалентенstr(x)
, а неformat(str(x), '')
.
- object.__lt__(self, other)¶
- object.__le__(self, other)¶
- object.__eq__(self, other)¶
- object.__ne__(self, other)¶
- object.__gt__(self, other)¶
- object.__ge__(self, other)¶
Это так называемые методы «богатого сравнения». Соответствие между символами операторов и именами методов следующее:
x<y
вызываетx.__lt__(y)
,x<=y
вызываетx.__le__(y)
,x==y
вызываетx.__eq__(y)
,x!=y
вызываетx.__ne__(y)
,x>y
вызываетx.__gt__(y)
иx>=y
вызываетx.__ge__(y)
.Метод богатого сравнения может возвращать синглтон
NotImplemented
, если он не реализует операцию для данной пары аргументов. По условию, при успешном сравнении возвращаются значенияFalse
иTrue
. Однако эти методы могут возвращать любое значение, поэтому если оператор сравнения используется в булевом контексте (например, в условии оператораif
), Python вызоветbool()
для значения, чтобы определить, является ли результат истинным или ложным.По умолчанию
object
реализует__eq__()
, используяis
, возвращаяNotImplemented
в случае ложного сравнения:True if x is y else NotImplemented
. Для__ne__()
по умолчанию делегируется__eq__()
и инвертирует результат, если он не равенNotImplemented
. Других подразумеваемых отношений между операторами сравнения или реализациями по умолчанию не существует; например, истинность(x<y or x==y)
не подразумеваетx<=y
. Чтобы автоматически генерировать операции упорядочивания из одной корневой операции, смотритеfunctools.total_ordering()
.См. параграф о
__hash__()
для некоторых важных замечаний по созданию объектов hashable, которые поддерживают пользовательские операции сравнения и могут использоваться в качестве ключей словаря.Не существует версий этих методов с подмененными аргументами (используемых в тех случаях, когда левый аргумент не поддерживает операцию, а правый поддерживает); скорее,
__lt__()
и__gt__()
являются отражением друг друга,__le__()
и__ge__()
- отражением друг друга, а__eq__()
и__ne__()
- собственным отражением. Если операнды разных типов, и тип правого операнда является прямым или косвенным подклассом типа левого операнда, приоритет имеет отраженный метод правого операнда, в противном случае приоритет имеет метод левого операнда. Виртуальный подкласс не рассматривается.Если ни один подходящий метод не возвращает значение, отличное от
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__()
объекта, до размераPy_ssize_t
. Обычно это 8 байт в 64-битных сборках и 4 байта в 32-битных сборках. Если__hash__()
объекта должен взаимодействовать со сборками с разным размером бит, обязательно проверьте ширину во всех поддерживаемых сборках. Простой способ сделать это - использоватьpython -c "import sys; print(sys.hash_info.width)"
.Если класс не определяет метод
__eq__()
, он не должен определять и операцию__hash__()
; если он определяет__eq__()
, но не__hash__()
, его экземпляры нельзя будет использовать в качестве элементов хэшируемых коллекций. Если класс определяет мутабельные объекты и реализует метод__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.Это предназначено для защиты от отказа в обслуживании, вызванного тщательно подобранными входными данными, которые используют наихудшую производительность вставки диктанта, 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__
теперь доступен для записи.
Added in version 3.7: Атрибуты модулей __getattr__
и __dir__
.
См.также
- PEP 562 - Модуль __getattr__ и __dir__
Описывает функции
__getattr__
и__dir__
на модулях.
3.3.2.2. Реализация дескрипторов¶
Следующие методы применяются только тогда, когда экземпляр класса, содержащего метод (так называемый класс дескриптор), появляется в классе владельца (дескриптор должен находиться либо в словаре классов владельца, либо в словаре классов одного из его родителей). В приведенных ниже примерах под «атрибутом» подразумевается атрибут, имя которого является ключом свойства в классе-владельце __dict__
.
- object.__get__(self, instance, owner=None)¶
Вызывается для получения атрибута класса-владельца (доступ к атрибуту класса) или экземпляра этого класса (доступ к атрибуту экземпляра). Необязательный аргумент owner - это класс-владелец, а instance - это экземпляр, через который был получен доступ к атрибуту, или
None
, если доступ к атрибуту осуществляется через owner.Этот метод должен возвращать вычисленное значение атрибута или вызывать исключение
AttributeError
.PEP 252 указывает, что
__get__()
можно вызывать с одним или двумя аргументами. Встроенные дескрипторы Python поддерживают эту спецификацию; однако, вероятно, некоторые сторонние инструменты имеют дескрипторы, требующие оба аргумента. Собственная реализация__getattribute__()
в Python всегда передает оба аргумента, независимо от того, требуются они или нет.
- object.__set__(self, instance, value)¶
Вызывается для установки атрибута экземпляра instance класса-владельца в новое значение, value.
Обратите внимание, что добавление
__set__()
или__delete__()
изменяет тип дескриптора на «дескриптор данных». Более подробную информацию см. в разделе Вызов дескрипторов.
- object.__delete__(self, instance)¶
Вызывается для удаления атрибута у экземпляра экземпляра класса-владельца.
У экземпляров дескрипторов также может присутствовать атрибут __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__:
При наследовании от класса без __slots__ атрибуты
__dict__
и __weakref__ экземпляров всегда будут доступны.Без переменной
__dict__
экземпляры не могут быть назначены новым переменным, не перечисленным в определении __slots__. Попытки присвоить имя переменной, не указанной в списке, приводят к появлениюAttributeError
. Если требуется динамическое присвоение новых переменных, то добавьте'__dict__'
к последовательности строк в объявлении __slots__.Без переменной __weakref__ для каждого экземпляра классы, определяющие __slots__, не поддерживают
weak references
для своих экземпляров. Если поддержка слабых ссылок необходима, то добавьте'__weakref__'
к последовательности строк в объявлении __slots__.__slots__ реализуются на уровне класса путем создания descriptors для каждого имени переменной. В результате атрибуты класса не могут быть использованы для установки значений по умолчанию для переменных экземпляра, определенных __slots__; в противном случае атрибут класса перезапишет назначение дескриптора.
Действие объявления __slots__ не ограничивается классом, в котором оно определено. Объявленные в родительском классе __slots__ доступны в дочерних классах. Однако дочерние подклассы получат
__dict__
и __weakref__, если они также не определят __slots__ (которые должны содержать только имена любых дополнительных слотов).Если класс определяет слот, также определенный в базовом классе, переменная экземпляра, определенная слотом базового класса, становится недоступной (за исключением получения ее дескриптора непосредственно из базового класса). Это делает смысл программы неопределенным. В будущем может быть добавлена проверка для предотвращения этого.
TypeError
будет поднят, если для класса, производного от"variable-length" built-in type
, такого какint
,bytes
иtuple
, определены непустые __slots__.Любая нестрока iterable может быть назначена на __slots__.
Если для назначения __слотов__ используется
dictionary
, то в качестве имен слотов будут использоваться ключи словаря. Значения словаря можно использовать для создания документальных строк для каждого атрибута, которые будут распознаватьсяinspect.getdoc()
и отображаться в выводеhelp()
.Назначение
__class__
работает только в том случае, если оба класса имеют одинаковые __slots__.Можно использовать Multiple inheritance с несколькими слотовыми родительскими классами, но только один родитель может иметь атрибуты, созданные слотами (остальные базы должны иметь пустые макеты слотов) - нарушения вызывают
TypeError
.Если для __slots__ используется iterator, то для каждого из значений итератора будет создан descriptor. Однако атрибут __slots__ будет пустым итератором.
3.3.3. Настройка создания классов¶
Когда класс наследует от другого класса, __init_subclass__()
вызывается на родительском классе. Таким образом, можно писать классы, которые изменяют поведение подклассов. Это тесно связано с декораторами классов, но если декораторы классов влияют только на конкретный класс, к которому они применяются, то __init_subclass__
применяется только к будущим подклассам класса, определяющего метод.
- classmethod object.__init_subclass__(cls)¶
Этот метод вызывается всякий раз, когда содержащий класс становится подклассом. В этом случае cls является новым подклассом. Если этот метод определен как обычный метод экземпляра, он неявно преобразуется в метод класса.
Аргументы ключевых слов, передаваемые новому классу, передаются в
__init_subclass__
родительского класса. Для совместимости с другими классами, использующими__init_subclass__
, следует убрать нужные аргументы ключевых слов, а остальные передать базовому классу, как в:class Philosopher: def __init_subclass__(cls, /, default_name, **kwargs): super().__init_subclass__(**kwargs) cls.default_name = default_name class AustralianPhilosopher(Philosopher, default_name="Bruce"): pass
Реализация по умолчанию
object.__init_subclass__
ничего не делает, но вызывает ошибку, если ее вызывают с какими-либо аргументами.Примечание
Подсказка метакласса
metaclass
потребляется остальными механизмами типов и никогда не передается реализациям__init_subclass__
. К реальному метаклассу (а не к явному намеку) можно обратиться как кtype(cls)
.Added in version 3.6.
Когда класс создан, type.__new__()
сканирует переменные класса и выполняет обратные вызовы к ним с помощью хука __set_name__()
.
- object.__set_name__(self, owner, name)¶
Автоматически вызывается при создании класса-владельца owner. Объект был назначен name в этом классе:
class A: x = C() # Automatically calls: x.__set_name__(A, 'x')
Если переменная класса назначена после создания класса, то
__set_name__()
не будет вызвана автоматически. При необходимости__set_name__()
можно вызвать напрямую:class A: pass c = C() A.x = c # The hook is not called c.__set_name__(A, 'x') # Manually invoke the hook
Более подробную информацию см. в разделе Создание объекта класса.
Added in version 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, и должен вернуть кортеж классов, которые будут использоваться вместо базы. Возвращаемый кортеж может быть пустым: в этом случае исходная база игнорируется.
См.также
types.resolve_bases()
Динамически разрешайте базы, которые не являются экземплярами
type
.types.get_original_bases()
Получение «исходных баз» класса до модификации
__mro_entries__()
.- PEP 560
Поддержка модуля типизации и общих типов.
3.3.3.3. Определение подходящего метакласса¶
Подходящий метакласс для определения класса определяется следующим образом:
если не указаны базы и явный метакласс, то используется
type()
;Если задан явный метакласс и он не является экземпляром
type()
, то он используется непосредственно в качестве метакласса;Если в качестве явного метакласса указан экземпляр
type()
или определены базы, то используется наиболее производный метакласс.
Наиболее производный метакласс выбирается из явно указанного метакласса (если таковой имеется) и метаклассов (т.е. type(cls)
) всех указанных базовых классов. Наиболее производным метаклассом является тот, который является подтипом всех этих метаклассов-кандидатов. Если ни один из метаклассов-кандидатов не удовлетворяет этому критерию, то определение класса завершится неудачей с результатом TypeError
.
3.3.3.4. Подготовка пространства имен класса¶
После определения подходящего метакласса подготавливается пространство имен класса. Если у метакласса есть атрибут __prepare__
, он вызывается как namespace = metaclass.__prepare__(name, bases, **kwds)
(при этом дополнительные аргументы-ключи, если таковые имеются, берутся из определения класса). Метод __prepare__
должен быть реализован как classmethod
. Пространство имен, возвращаемое __prepare__
, передается в __new__
, но при создании конечного объекта класса это пространство имен копируется в новый dict
.
Если у метакласса нет атрибута __prepare__
, то пространство имен класса инициализируется как пустое упорядоченное отображение.
См.также
- PEP 3115 - Метаклассы в Python 3000
Введено крючок пространства имен
__prepare__
.
3.3.3.5. Выполнение тела класса¶
Тело класса выполняется (приблизительно) как exec(body, globals(), namespace)
. Ключевое отличие от обычного вызова exec()
заключается в том, что лексический охват позволяет телу класса (включая любые методы) ссылаться на имена из текущего и внешнего охватов, когда определение класса находится внутри функции.
Однако даже если определение класса находится внутри функции, методы, определенные внутри класса, все равно не могут видеть имена, определенные в области видимости класса. Доступ к переменным класса должен осуществляться через первый параметр методов экземпляра или класса, либо через неявную лексически развернутую ссылку __class__
, описанную в следующем разделе.
3.3.3.6. Создание объекта класса¶
После того как пространство имен класса было заполнено путем выполнения тела класса, объект класса создается вызовом metaclass(name, bases, namespace, **kwds)
(дополнительные ключевые слова, передаваемые здесь, аналогичны тем, что передаются в __prepare__
).
Именно на этот объект класса будет ссылаться нулевой аргумент super()
. __class__
- это неявная ссылка на закрытие, создаваемая компилятором, если какие-либо методы в теле класса ссылаются на __class__
или super
. Это позволяет форме super()
с нулевым аргументом правильно идентифицировать определяемый класс на основе лексического анализа, в то время как класс или экземпляр, который был использован для текущего вызова, идентифицируется на основе первого аргумента, переданного методу.
Детали реализации CPython: В CPython 3.6 и более поздних версиях ячейка __class__
передается в метакласс как запись __classcell__
в пространстве имен класса. Если она присутствует, ее необходимо распространить до вызова type.__new__
, чтобы класс был инициализирован правильно. Если этого не сделать, то в Python 3.8 это приведет к ошибке RuntimeError
.
При использовании метакласса по умолчанию type
или любого метакласса, который в конечном итоге вызывает type.__new__
, после создания объекта класса выполняются следующие дополнительные действия по настройке:
Метод
type.__new__
собирает все атрибуты в пространстве имен класса, которые определяют метод__set_name__()
;Эти методы
__set_name__
вызываются с указанием определяемого класса и назначенного имени конкретного атрибута;Хук
__init_subclass__()
вызывается на непосредственном родителе нового класса в порядке разрешения его методов.
После создания объекта класса он передается декораторам класса, включенным в определение класса (если таковые имеются), и полученный объект привязывается в локальном пространстве имен к определенному классу.
Когда новый класс создается с помощью type.__new__
, объект, указанный в качестве параметра пространства имен, копируется в новое упорядоченное отображение, а исходный объект отбрасывается. Новая копия оборачивается в прокси, доступный только для чтения, который становится атрибутом __dict__
объекта класса.
См.также
- PEP 3135 - Новый супер
Описывает неявную ссылку на закрытие
__class__
.
3.3.3.7. Использование метаклассов¶
Потенциальные возможности использования метаклассов безграничны. Некоторые идеи, которые были рассмотрены, включают в себя перечисления, протоколирование, проверку интерфейса, автоматическое делегирование, автоматическое создание свойств, прокси, фреймворки и автоматическую блокировку/синхронизацию ресурсов.
3.3.4. Настройка проверок экземпляров и подклассов¶
Следующие методы используются для переопределения поведения по умолчанию встроенных функций isinstance()
и issubclass()
.
В частности, метакласс abc.ABCMeta
реализует эти методы, чтобы позволить добавлять абстрактные базовые классы (ABC) в качестве «виртуальных базовых классов» к любому классу или типу (включая встроенные типы), в том числе к другим ABC.
- class.__instancecheck__(self, instance)¶
Возвращает true, если instance следует считать (прямым или косвенным) экземпляром class. Если определено, вызывается для реализации
isinstance(instance, class)
.
- class.__subclasscheck__(self, subclass)¶
Возвращает true, если subclass следует считать (прямым или косвенным) подклассом class. Если определено, вызывается для реализации
issubclass(subclass, class)
.
Обратите внимание, что эти методы ищутся в типе (метаклассе) класса. Они не могут быть определены как методы класса в самом классе. Это соответствует поиску специальных методов, которые вызываются у экземпляров, только в этом случае экземпляр сам является классом.
См.также
- PEP 3119 - Представляем абстрактные базовые классы
Включает спецификацию для настройки поведения
isinstance()
иissubclass()
через__instancecheck__()
и__subclasscheck__()
, с мотивацией этой функциональности в контексте добавления в язык абстрактных базовых классов (см. модульabc
).
3.3.5. Эмуляция общих типов¶
При использовании type annotations часто полезно параметризировать generic type, используя нотацию квадратных скобок Python. Например, аннотация list[int]
может использоваться для обозначения list
, в котором все элементы имеют тип int
.
См.также
- PEP 484 - Тип Подсказки
Знакомство с основой Python для аннотаций типов
- Generic Alias Types
Документация для объектов, представляющих параметризованные общие классы
- Дженерики, user-defined generics и
typing.Generic
. Документация о том, как реализовать общие классы, которые могут быть параметризованы во время выполнения и поняты статическими средствами проверки типов.
Класс, как правило, может быть параметризован только в том случае, если он определяет специальный метод класса __class_getitem__()
.
- classmethod object.__class_getitem__(cls, key)¶
Возвращает объект, представляющий специализацию общего класса по аргументам типа, найденным в key.
Когда
__class_getitem__()
определен на классе, он автоматически является методом класса. Поэтому нет необходимости украшать его@classmethod
, когда он определен.
3.3.5.1. Назначение __class_getitem__.¶
Цель __class_getitem__()
- позволить параметризацию во время выполнения стандартных библиотек общих классов, чтобы легче было применять type hints к этим классам.
Чтобы реализовать собственные общие классы, которые могут быть параметризованы во время выполнения и поняты статическими средствами проверки типов, пользователи должны либо наследоваться от стандартного библиотечного класса, который уже реализует __class_getitem__()
, либо наследоваться от typing.Generic
, который имеет свою собственную реализацию __class_getitem__()
.
Пользовательские реализации __class_getitem__()
для классов, определенных вне стандартной библиотеки, могут быть не поняты сторонними программами проверки типов, такими как mypy. Использование __class_getitem__()
в любом классе для целей, отличных от подсказки типа, не рекомендуется.
3.3.5.2. __class_getitem__ против __getitem__¶
Обычно subscription объекта, заключенного в квадратные скобки, вызывает метод экземпляра __getitem__()
, определенный для класса объекта. Однако если подписываемый объект сам является классом, вместо него может быть вызван метод класса __class_getitem__()
. Метод __class_getitem__()
должен возвращать объект GenericAlias, если он правильно определен.
Представляя expression obj[x]
, интерпретатор Python принимает решение о том, следует ли вызывать __getitem__()
или __class_getitem__()
, примерно следующим образом:
from inspect import isclass
def subscribe(obj, x):
"""Return the result of the expression 'obj[x]'"""
class_of_obj = type(obj)
# If the class of obj defines __getitem__,
# call class_of_obj.__getitem__(obj, x)
if hasattr(class_of_obj, '__getitem__'):
return class_of_obj.__getitem__(obj, x)
# Else, if obj is a class and defines __class_getitem__,
# call obj.__class_getitem__(x)
elif isclass(obj) and hasattr(obj, '__class_getitem__'):
return obj.__class_getitem__(x)
# Else, raise an exception
else:
raise TypeError(
f"'{class_of_obj.__name__}' object is not subscriptable"
)
В Python все классы сами являются экземплярами других классов. Класс класса известен как metaclass этого класса, а большинство классов имеют класс type
в качестве своего метакласса. type
не определяет __getitem__()
, а значит, такие выражения, как list[int]
, dict[str, float]
и tuple[str, bytes]
, приводят к вызову __class_getitem__()
:
>>> # list has class "type" as its metaclass, like most classes:
>>> type(list)
<class 'type'>
>>> type(dict) == type(list) == type(tuple) == type(str) == type(bytes)
True
>>> # "list[int]" calls "list.__class_getitem__(int)"
>>> list[int]
list[int]
>>> # list.__class_getitem__ returns a GenericAlias object:
>>> type(list[int])
<class 'types.GenericAlias'>
Однако если класс имеет пользовательский метакласс, определяющий __getitem__()
, подписка на него может привести к другому поведению. Пример этого можно найти в модуле enum
:
>>> from enum import Enum
>>> class Menu(Enum):
... """A breakfast menu"""
... SPAM = 'spam'
... BACON = 'bacon'
...
>>> # Enum classes have a custom metaclass:
>>> type(Menu)
<class 'enum.EnumMeta'>
>>> # EnumMeta defines __getitem__,
>>> # so __class_getitem__ is not called,
>>> # and the result is not a GenericAlias object:
>>> Menu['SPAM']
<Menu.SPAM: 'spam'>
>>> type(Menu['SPAM'])
<enum 'Menu'>
См.также
- PEP 560 - Ядро Поддержка типизации модульных и общих типов
Представляем
__class_getitem__()
и рассказываем, в каких случаях subscription приводит к вызову__class_getitem__()
вместо__getitem__()
.
3.3.6. Эмуляция вызываемых объектов¶
- object.__call__(self[, args...])¶
Вызывается, когда экземпляр «вызывается» как функция; если этот метод определен, то
x(arg1, arg2, ...)
примерно равняетсяtype(x).__call__(x, arg1, ...)
.
3.3.7. Эмуляция типов контейнеров¶
Следующие методы могут быть определены для реализации объектов-контейнеров. Обычно контейнеры представляют собой sequences (например, lists
или tuples
) или mappings (например, dictionaries
), но могут представлять и другие контейнеры. Первый набор методов используется либо для эмуляции последовательности, либо для эмуляции отображения; разница в том, что для последовательности допустимыми ключами должны быть целые числа k, для которых 0 <= k < N
, где N - длина последовательности, или объекты slice
, которые определяют диапазон элементов. Также рекомендуется, чтобы отображения предоставляли методы keys()
, values()
, items()
, get()
, clear()
, setdefault()
, pop()
, popitem()
, copy()
и update()
, которые ведут себя аналогично методам для стандартных dictionary
объектов Python. Модуль collections.abc
предоставляет MutableMapping
abstract base class, чтобы помочь создать эти методы из базового набора __getitem__()
, __setitem__()
, __delitem__()
и keys()
. Мутабельные последовательности должны предоставлять методы append()
, count()
, index()
, extend()
, insert()
, pop()
, remove()
, reverse()
и sort()
, подобно объектам list
стандарта Python. Наконец, типы последовательностей должны реализовывать сложение (то есть конкатенацию) и умножение (то есть повторение), определяя методы __add__()
, __radd__()
, __iadd__()
, __mul__()
, __rmul__()
и __imul__()
, описанные ниже; они не должны определять другие числовые операторы. Рекомендуется, чтобы и отображения, и последовательности реализовывали метод __contains__()
для эффективного использования оператора in
; для отображений in
должен искать ключи отображения, а для последовательностей - значения. Кроме того, рекомендуется, чтобы и отображения, и последовательности
- 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__
вообще не существовал. Этот метод является исключительно оптимизацией и никогда не требуется для корректности.Added in version 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, если key отсутствует (нет в контейнере), должно быть вызвано сообщениеKeyError
.Примечание
Циклы
for
ожидают, что для недопустимых индексов будет вызван сигналIndexError
, чтобы правильно определить конец последовательности.Примечание
Если subscripting является классом, вместо
__getitem__()
может быть вызван специальный метод класса__class_getitem__()
. Более подробную информацию см. в разделе __class_getitem__ против __getitem__.
- object.__setitem__(self, key, value)¶
Вызывается для реализации присвоения
self[key]
. То же замечание, что и для__getitem__()
. Это должно быть реализовано только для отображений, если объекты поддерживают изменение значений ключей, или если можно добавлять новые ключи, или для последовательностей, если можно заменять элементы. Для неправильных значений ключей должны возникать те же исключения, что и для метода__getitem__()
.
- object.__delitem__(self, key)¶
Вызывается для реализации удаления
self[key]
. То же замечание, что и для__getitem__()
. Это должно быть реализовано только для отображений, если объекты поддерживают удаление ключей, или для последовательностей, если элементы могут быть удалены из последовательности. Для неправильных значений ключей должны возникать те же исключения, что и для метода__getitem__()
.
- object.__missing__(self, key)¶
Вызывается
dict
.__getitem__()
для реализацииself[key]
для подклассов dict, когда ключ не находится в словаре.
- object.__iter__(self)¶
Этот метод вызывается, когда для контейнера требуется iterator. Этот метод должен возвращать новый объект-итератор, который может перебирать все объекты в контейнере. Для отображений он должен перебирать ключи контейнера.
- object.__reversed__(self)¶
Вызывается (если присутствует) встроенным
reversed()
для реализации обратной итерации. Он должен возвращать новый объект-итератор, который перебирает все объекты в контейнере в обратном порядке.Если метод
__reversed__()
не предоставлен, встроенныйreversed()
вернется к использованию протокола последовательности (__len__()
и__getitem__()
). Объекты, поддерживающие протокол последовательности, должны предоставлять__reversed__()
только в том случае, если они могут обеспечить реализацию, более эффективную, чем та, что предоставляетсяreversed()
.
Операторы проверки принадлежности (in
и not in
) обычно реализуются как итерация через контейнер. Однако объекты-контейнеры могут предоставить следующий специальный метод с более эффективной реализацией, который также не требует, чтобы объект был итерируемым.
- object.__contains__(self, item)¶
Вызывается для реализации операторов проверки принадлежности. Должен возвращать true, если item находится в self, false в противном случае. Для объектов отображения должны учитываться ключи отображения, а не значения или пары ключ-элемент.
Для объектов, которые не определяют
__contains__()
, тест членства сначала пробует итерацию через__iter__()
, затем старый протокол итерации последовательности через__getitem__()
, см. this section in the language reference.
3.3.8. Эмуляция числовых типов¶
Для эмуляции числовых объектов могут быть определены следующие методы. Методы, соответствующие операциям, которые не поддерживаются конкретным видом реализуемого числа (например, побитовые операции для неинтегральных чисел), следует оставить неопределенными.
- object.__add__(self, other)¶
- object.__sub__(self, other)¶
- object.__mul__(self, other)¶
- object.__matmul__(self, other)¶
- object.__truediv__(self, other)¶
- object.__floordiv__(self, other)¶
- object.__mod__(self, other)¶
- object.__divmod__(self, other)¶
- object.__pow__(self, other[, modulo])¶
- object.__lshift__(self, other)¶
- object.__rshift__(self, other)¶
- object.__and__(self, other)¶
- object.__xor__(self, other)¶
- object.__or__(self, other)¶
Эти методы вызываются для реализации операций двоичной арифметики (
+
,-
,*
,@
,/
,//
,%
,divmod()
,pow()
,**
,<<
,>>
,&
,^
,|
). Например, для оценки выраженияx + y
, где x - экземпляр класса, имеющего метод__add__()
, вызывается метод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()
). Наличие этого метода указывает на то, что числовой объект является типом integer. Должен возвращать целое число.Если
__int__()
,__float__()
и__complex__()
не определены, то соответствующие встроенные функцииint()
,float()
иcomplex()
возвращаются к__index__()
.
- object.__round__(self[, ndigits])¶
- object.__trunc__(self)¶
- object.__floor__(self)¶
- object.__ceil__(self)¶
Вызывается для реализации встроенной функции
round()
иmath
функцийtrunc()
,floor()
иceil()
. Если в__round__()
не передано значение ndigits, все эти методы должны возвращать значение объекта, усеченное доIntegral
(обычноint
).Изменено в версии 3.14:
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
.
Added in version 3.10.
См.также
- PEP 634 - Структурное сопоставление шаблонов
Спецификация для оператора Python
match
.
3.3.11. Эмуляция типов буферов¶
Протокол buffer protocol предоставляет объектам Python возможность эффективного доступа к низкоуровневому массиву памяти. Этот протокол реализуется встроенными типами, такими как bytes
и memoryview
, а сторонние библиотеки могут определять дополнительные типы буферов.
Хотя типы буферов обычно реализуются на языке C, протокол можно реализовать и на Python.
- object.__buffer__(self, flags)¶
Вызывается, когда буфер запрашивается у self (например, конструктором
memoryview
). Аргумент flags - это целое число, представляющее тип запрашиваемого буфера, влияющее, например, на то, будет ли возвращаемый буфер доступен только для чтения или для записи.inspect.BufferFlags
предоставляет удобный способ интерпретации флагов. Метод должен возвращать объектmemoryview
.
- object.__release_buffer__(self, buffer)¶
Вызывается, когда буфер больше не нужен. Аргумент buffer - это объект
memoryview
, который ранее был возвращен методом__buffer__()
. Метод должен освободить все ресурсы, связанные с буфером. Этот метод должен возвращатьNone
. Объекты буфера, которым не нужно выполнять очистку, не обязаны реализовывать этот метод.
Added in version 3.12.
См.также
- PEP 688 - Создание буферного протокола в Python
Представляет методы Python
__buffer__
и__release_buffer__
.collections.abc.Buffer
ABC для типов буферов.
3.3.12. Поиск специального метода¶
Для пользовательских классов неявные вызовы специальных методов гарантированно работают корректно только в том случае, если они определены в типе объекта, а не в словаре экземпляров объекта. Такое поведение является причиной того, что следующий код вызывает исключение:
>>> 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
.
Added in version 3.5.
См.также
PEP 492 для получения дополнительной информации об ожидаемых объектах.
3.4.2. Объекты корутины¶
Coroutine objects являются объектами awaitable. Выполнение корутины можно контролировать, вызывая __await__()
и выполняя итерацию по результату. Когда корутина завершает выполнение и возвращается, итератор поднимает StopIteration
, а атрибут value
исключения содержит возвращаемое значение. Если короутин вызывает исключение, оно передается итератору. Корутины не должны напрямую вызывать необработанные StopIteration
исключения.
Корутины также имеют перечисленные ниже методы, которые аналогичны методам генераторов (см. Методы генератора-итератора). Однако, в отличие от генераторов, корутины не поддерживают итерацию напрямую.
Изменено в версии 3.5.2: Ожидать выполнения coroutine более одного раза - это RuntimeError
.
- coroutine.send(value)¶
Запускает или возобновляет выполнение корутины. Если value равно
None
, это эквивалентно продвижению итератора, возвращенного__await__()
. Если значение не равноNone
, этот метод делегирует методsend()
того итератора, который вызвал приостановку работы короутина. Результат (возвращаемое значение,StopIteration
или другое исключение) тот же, что и при итерации по возвращаемому значению__await__()
, описанной выше.
- coroutine.throw(value)¶
- coroutine.throw(type[, value[, traceback]])
Вызывает указанное исключение в корутине. Этот метод делегирует полномочия методу
throw()
итератора, вызвавшего приостановку коротины, если у него есть такой метод. В противном случае исключение вызывается в точке приостановки. Результат (возвращаемое значение,StopIteration
или другое исключение) тот же, что и при итерации по возвращаемому значению__await__()
, описанной выше. Если исключение не было поймано в корутине, оно передается обратно вызывающей стороне.Изменено в версии 3.12: Вторая сигнатура (type[, value[, traceback]]]) устарела и может быть удалена в будущей версии Python.
- coroutine.close()¶
Приводит к очистке и завершению работы корутины. Если выполнение коридора приостановлено, этот метод сначала делегирует метод
close()
итератора, который вызвал приостановку коридора, если у него есть такой метод. Затем он поднимаетGeneratorExit
в точке приостановки, заставляя coroutine немедленно очистить себя. И наконец, coroutine помечается как завершившая выполнение, даже если она никогда не была запущена.Объекты Coroutine автоматически закрываются с помощью описанного выше процесса, когда они собираются быть уничтоженными.
3.4.3. Асинхронные итераторы¶
Асинхронный итератор* может вызывать асинхронный код в своем методе __anext__
.
Асинхронные итераторы можно использовать в операторе async for
.
- object.__aiter__(self)¶
Должен возвращать объект асинхронного итератора.
- object.__anext__(self)¶
Должен возвращать ожидание, приводящее к следующему значению итератора. Должна вызывать ошибку
StopAsyncIteration
, когда итерация завершается.
Пример асинхронного итерируемого объекта:
class Reader:
async def readline(self):
...
def __aiter__(self):
return self
async def __anext__(self):
val = await self.readline()
if val == b'':
raise StopAsyncIteration
return val
Added in version 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')
Added in version 3.5.
Сноски