Модель данных
3.1. Объекты, значения и типы
Объекты — это абстракция данных в Python. Все данные в программе Python представлены объектами или отношениями между объектами. (В некотором смысле, и в соответствии с моделью фон Неймана «компьютера с хранимой программой», код также представлен объектами.)
Каждый объект имеет идентификатор, тип и значение. Идентификатор объекта не изменяется после его создания; можно представить его как адрес объекта в памяти. Оператор ‘is’ сравнивает идентификаторы двух объектов; функция id() возвращает целое число, представляющее его идентификатор.
Подробность реализации CPython: Для CPython, id(x) — это адрес памяти, где хранится x.
Тип объекта определяет операции, которые поддерживает объект (например, «имеет ли он длину?»), а также определяет возможные значения для объектов этого типа. Функция type() возвращает тип объекта (который сам является объектом). Как и его идентификатор, тип объекта также неизменен. 1
Значение некоторых объектов может изменяться. Объекты, значение которых может изменяться, называются изменяемыми; объекты, значение которых неизменяемо после создания, называются неизменяемыми. (Значение неизменяемого контейнерного объекта, содержащего ссылку на изменяемый объект, может измениться, когда значение последнего изменяется; однако контейнер по-прежнему считается неизменяемым, потому что набор объектов, которые он содержит, изменить нельзя. Таким образом, неизменяемость не строго эквивалентна наличию неизменяемого значения, это более тонкое понятие.) Изменяемость объекта определяется его типом; например, числа, строки и кортежи являются неизменяемыми, а словари и списки — изменяемыми.
Объекты никогда не уничтожаются явно; однако, когда они становятся недоступными, они могут быть собраны сборщиком мусора. Реализация может отложить сборку мусора или вообще отказаться от неё — качество реализации заключается в том, как реализован сборщик мусора, при условии, что не будут собраны объекты, которые все еще доступны.
Подробность реализации CPython: CPython в настоящее время использует схему подсчёта ссылок с (необязательным) отложенным обнаружением циклических ссылок, которая собирает большинство объектов сразу, как они становятся недоступными, но не гарантирует сборку мусора, содержащего циклические ссылки. См. документацию модуля gc для получения информации об управлении сбором циклического мусора. Другие реализации действуют иначе, и CPython может измениться. Не полагайтесь на немедленное завершение объектов, когда они становятся недоступными (поэтому вы всегда должны явно закрывать файлы).
Обратите внимание, что использование средств отладки или трассировки реализации может сохранять объекты, которые обычно должны быть собраны. Также обратите внимание, что перехват исключения с помощью оператора ‘try…except’ может сохранять объекты.
Некоторые объекты содержат ссылки на «внешние» ресурсы, такие как открытые файлы или окна. Понимается, что эти ресурсы освобождаются при сборе мусора объекта, но поскольку сборка мусора не гарантируется, такие объекты также предоставляют явный способ освободить внешний ресурс, обычно метод close(). Программам настоятельно рекомендуется явно закрывать такие объекты. Оператор ‘try…finally’ и оператор ‘with’ обеспечивают удобные способы для этого.
Некоторые объекты содержат ссылки на другие объекты; они называются контейнерами. Примерами контейнеров являются кортежи, списки и словари. Ссылки являются частью значения контейнера. В большинстве случаев, когда мы говорим о значении контейнера, мы подразумеваем значения, а не идентификаторы содержащихся объектов; однако, когда мы говорим об изменяемости контейнера, подразумеваются только идентификаторы непосредственно содержащихся объектов. Таким образом, если неизменяемый контейнер (например, кортеж) содержит ссылку на изменяемый объект, его значение изменяется, если значение этого изменяемого объекта изменяется.
Типы влияют на практически все аспекты поведения объекта. Даже важность идентификатора объекта в некотором смысле затрагивается: для неизменяемых типов операции, вычисляющие новые значения, могут фактически вернуть ссылку на любой существующий объект с тем же типом и значением, а для изменяемых объектов это недопустимо. Например, после a = 1; b = 1, a и b могут или не могут ссылаться на один и тот же объект со значением один, в зависимости от реализации, но после c = []; d =
[], c и d гарантированно ссылаются на два разных, уникальных, недавно созданных пустых списка. (Обратите внимание, что c = d = [] присваивает один и тот же объект как c, так и d.)
3.2. Стандартная иерархия типов
Ниже приведён список встроенных типов Python. Дополнительные модули (написанные на C, Java или других языках в зависимости от реализации) могут определять дополнительные типы. Будущие версии Python могут добавить типы в иерархию типов (например, рациональные числа, эффективно хранимые массивы целых чисел и т. д.), хотя такие добавления часто будут предоставлены через стандартную библиотеку.
Некоторые описания типов ниже содержат абзац со «специальными атрибутами». Это атрибуты, которые обеспечивают доступ к реализации и не предназначены для общего использования. Их определение может измениться в будущем.
- None
-
Этот тип имеет единственное значение. Существует один объект с этим значением. К этому объекту можно обратиться по встроенному имени
None. Он используется для обозначения отсутствия значения во многих ситуациях, например, он возвращается из функций, которые не явно ничего не возвращают. Его значение истинности — ложь. - NotImplemented
-
Этот тип имеет единственное значение. Существует один объект с этим значением. К этому объекту можно обратиться по встроенному имени
NotImplemented. Числовые методы и методы богатого сравнения должны возвращать это значение, если они не реализуют операцию для предоставленных операндов. (Интерпретатор затем попытается выполнить отражённую операцию или использовать другой способ обработки, в зависимости от оператора.) Его не следует оценивать в контексте булевых значений.См. Реализация арифметических операций для получения более подробной информации.
Изменено в версии 3.9: Оценивание
NotImplementedв контексте булевых значений устарело. Хотя в настоящее время оно оценивается как истинное, будет выведено предупреждениеDeprecationWarning. В будущей версии Python оно вызовет исключениеTypeError. - Ellipsis
-
Этот тип имеет единственное значение. Существует один объект с этим значением. К этому объекту можно обратиться по литералу
...или встроенному имениEllipsis. Его значение истинности — истина. -
numbers.Number -
Они создаются числовыми литералами и возвращаются в качестве результатов арифметическими операторами и встроенными арифметическими функциями. Числовые объекты неизменяемы; после создания их значение никогда не меняется. Числа в Python, конечно, тесно связаны с математическими числами, но подчиняются ограничениям числового представления в компьютерах.
Строковые представления числовых классов, вычисленные с помощью
__repr__()и__str__(), обладают следующими свойствами:- Они являются допустимыми числовыми литералами, которые, при передаче в конструктор их класса, создают объект, имеющий значение исходного числового.
- Представление в десятичной системе счисления, когда это возможно.
- Лишние нули, возможно за исключением одного нуля перед десятичной точкой, не отображаются.
- Лишние нули, возможно за исключением одного нуля после десятичной точки, не отображаются.
- Знак отображается только тогда, когда число отрицательное.
Python различает целые числа, числа с плавающей точкой и комплексные числа:
-
numbers.Integral -
Они представляют элементы из математического множества целых чисел (положительных и отрицательных).
Существует два типа целых чисел:
-
Integers (int) -
Они представляют числа в неограниченном диапазоне, ограниченном только доступной (виртуальной) памятью. Для целей операций сдвига и маски предполагается двоичное представление, а отрицательные числа представляются с помощью варианта дополнительного кода, который даёт иллюзию бесконечной строки битов знака, простирающейся влево.
-
Booleans (bool) -
Они представляют значения истинности False и True. Два объекта, представляющие значения
FalseиTrue, являются единственными булевыми объектами. Булевый тип является подтипом целочисленного типа, и булевы значения ведут себя как значения 0 и 1 соответственно, практически во всех контекстах, исключением является то, что при преобразовании в строку возвращаются строки"False"или"True"соответственно.
Правила представления целых чисел предназначены для обеспечения наиболее осмысленной интерпретации операций сдвига и маски, связанных с отрицательными целыми числами.
-
-
numbers.Real (float) -
Они представляют числа с плавающей точкой двойной точности на уровне машины. Вы зависите от архитектуры базовой машины (и реализации C или Java) для принятого диапазона и обработки переполнения. Python не поддерживает числа с плавающей точкой одинарной точности; экономия ресурсов процессора и памяти, которая обычно является причиной использования таких чисел, ничтожна по сравнению с накладными расходами использования объектов в Python, поэтому нет оснований усложнять язык двумя типами чисел с плавающей точкой.
-
numbers.Complex (complex) -
Они представляют комплексные числа как пару чисел с плавающей точкой двойной точности на уровне машины. Применимы те же замечания, что и для чисел с плавающей точкой. Действительную и мнимую части комплексного числа
zможно получить через неизменяемые атрибутыz.realиz.imag.
- Последовательности
-
Они представляют конечные упорядоченные наборы, индексированные неотрицательными числами. Встроенная функция
len()возвращает количество элементов последовательности. Когда длина последовательности равна n, множество индексов содержит числа 0, 1, …, n-1. Элемент i последовательности a выбирается с помощьюa[i].Последовательности также поддерживают срезы:
a[i:j]выбирает все элементы с индексом k, такие что i<=k<j. При использовании в качестве выражения срез является последовательностью того же типа. Это подразумевает, что множество индексов переиндексировано так, что оно начинается с 0.Некоторые последовательности также поддерживают «расширенные срезы» с третьим параметром «шаг»:
a[i:j:k]выбирает все элементы a с индексом x, гдеx = i + n*k, n>=0и i<=x<j.Последовательности различаются по своей изменяемости:
- Неизменяемые последовательности
-
Объект неизменяемого типа последовательности не может быть изменён после его создания. (Если объект содержит ссылки на другие объекты, эти другие объекты могут быть изменяемыми и могут быть изменены; однако, набор объектов, непосредственно ссылающихся на объект неизменяемого типа, не может измениться.)
Следующие типы являются неизменяемыми последовательностями:
- Строки
-
Строка — это последовательность значений, представляющих точки кода Юникода. Все точки кода в диапазоне
U+0000 - U+10FFFFмогут быть представлены в строке. В Python нет типаchar; вместо этого каждая точка кода в строке представляется объектом строки длиной1. Встроенная функцияord()преобразует точку кода из её строковой формы в целое число в диапазоне0 - 10FFFF;chr()преобразует целое число в диапазоне0 - 10FFFFв соответствующий объект строки длиной1.str.encode()можно использовать для преобразованияstrвbytesс использованием заданной кодировки текста, аbytes.decode()можно использовать для достижения обратного результата. - Кортежи
-
Элементы кортежа — произвольные объекты Python. Кортежи из двух или более элементов формируются перечислением выражений через запятые. Кортеж из одного элемента («одиночный») может быть сформирован путём добавления запятой к выражению (само по себе выражение не создаёт кортеж, так как скобки должны использоваться для группировки выражений). Пустой кортеж может быть сформирован пустой парой скобок.
- Bytes
-
Объект bytes — это неизменяемый массив. Элементы — это байты длиной 8 бит, представленные целыми числами в диапазоне 0 <= x < 256. Литералы bytes (например,
b'abc') и встроенный конструкторbytes()могут использоваться для создания объектов bytes. Также объекты bytes могут быть декодированы в строки с помощью методаdecode().
- Изменяемые последовательности
-
Изменяемые последовательности могут быть изменены после их создания. Операторы индексации и срезов могут использоваться в качестве цели присваивания и оператора
del(удаление).В настоящее время существует два встроенных типа изменяемых последовательностей:
- Списки
-
Элементы списка — произвольные объекты Python. Списки формируются с помощью перечисления выражений через запятые в квадратных скобках. (Обратите внимание, что для формирования списков длиной 0 или 1 не нужны специальные случаи.)
- Массивы байтов
-
Объект bytearray — это изменяемый массив. Они создаются встроенным конструктором
bytearray(). Помимо изменяемости (и, следовательно, неизменяемости) массивы байтов иначе обеспечивают тот же интерфейс и функциональность, что и неизменяемыеbytesобъекты.
Модуль расширения
arrayпредоставляет дополнительный пример типа изменяемой последовательности, как и модульcollections.
- Типы множеств
-
Они представляют собой неупорядоченные конечные множества уникальных неизменяемых объектов. Таким образом, к ним нельзя обратиться по индексу. Однако они могут быть перебраны, а встроенная функция
len()возвращает количество элементов в множестве. Типичные применения множеств — быстрая проверка принадлежности, удаление дубликатов из последовательности и вычисление математических операций, таких как пересечение, объединение, разность и симметрическая разность.Для элементов множества применяются те же правила неизменяемости, что и для ключей словарей. Обратите внимание, что числовые типы подчиняются обычным правилам сравнения чисел: если два числа равны (например,
1и1.0), только одно из них может содержаться в множестве.В настоящее время существует два встроенных типа множеств:
- Множества
-
Они представляют собой изменяемое множество. Они создаются с помощью встроенного
set()конструктора и могут быть изменены после создания несколькими методами, такими какadd(). - Замороженные множества
-
Они представляют собой неизменяемое множество. Они создаются с помощью встроенного
frozenset()конструктора. Поскольку frozenset неизменяем и хешируем, его можно снова использовать как элемент другого множества или как ключ словаря.
- Отображения
-
Они представляют собой конечные множества объектов, индексированные произвольными наборами индексов. Нотация по индексу
a[k]выбирает элемент, индексированныйkиз отображенияa; это можно использовать в выражениях и в качестве цели присваивания или операторовdel. Встроенная функцияlen()возвращает количество элементов в отображении.В настоящее время существует один встроенный тип отображения:
- Словари
-
Они представляют собой конечные наборы объектов, индексированные почти произвольными значениями. Единственные типы значений, неприемлемые в качестве ключей, — это значения, содержащие списки или словари или другие изменяемые типы, которые сравниваются по значению, а не по идентификатору объекта; причина заключается в том, что для эффективной реализации словарей требуется, чтобы значение хэша ключа оставалось постоянным. Числовые типы, используемые в качестве ключей, подчиняются обычным правилам сравнения чисел: если два числа равны (например,
1и1.0), их можно использовать взаимозаменяемо для индексации одной и той же записи словаря.Словари сохраняют порядок вставки, что означает, что ключи будут получены в том же порядке, в котором они были добавлены последовательно в словарь. Замена существующего ключа не изменяет порядок, однако удаление ключа и повторная вставка добавят его в конец вместо сохранения его старого места.
Словари изменяемы; они могут быть созданы с помощью записи
{...}(см. раздел Отображения словарей).Модули расширений
dbm.ndbmиdbm.gnuпредоставляют дополнительные примеры типов отображений, как и модульcollections.Изменено в версии 3.7: Словари не сохраняли порядок вставки в версиях Python до 3.6. В CPython 3.6 порядок вставки сохранялся, но в то время это считалось деталью реализации, а не гарантией языка.
- Вызываемые типы
-
Это типы, к которым может быть применено операция вызова функции (см. раздел Вызовы):
- Определённые пользователем функции
-
Объект функции, определённой пользователем, создаётся с помощью определения функции (см. раздел Определения функций). Она должна вызываться со списком аргументов, содержащим такое же количество элементов, что и формальный список параметров функции.
Специальные атрибуты:
Атрибут
Значение
__doc__Строка документации функции или
None, если недоступна; не наследуется подклассами.Записываемый
Имя функции.
Записываемый
Полное имя функции.
Введено в версии 3.3.
Записываемый
__module__Имя модуля, в котором была определена функция, или
None, если недоступно.Записываемый
__defaults__Кортеж, содержащий значения по умолчанию для тех аргументов, которые имеют значения по умолчанию, или
None, если ни один аргумент не имеет значения по умолчанию.Записываемый
__code__Объект кода, представляющий скомпилированное тело функции.
Записываемый
__globals__Ссылка на словарь, который хранит глобальные переменные функции — глобальное пространство имён модуля, в котором была определена функция.
Только для чтения
Пространство имён, поддерживающее произвольные атрибуты функции.
Записываемый
__closure__Noneили кортеж ячеек, содержащих привязки к свободным переменным функции. Смотрите ниже информацию об атрибутеcell_contents.Только для чтения
__annotations__Словарь, содержащий аннотации параметров. Ключами словаря являются имена параметров, а также
'return'для аннотации возвращаемого значения, если она указана.Записываемый
__kwdefaults__Словарь, содержащий значения по умолчанию для параметров, только для ключевых слов.
Записываемый
Большинство атрибутов, помеченных как «Записываемый», проверяют тип присвоенного значения.
Объекты функций также поддерживают получение и установку произвольных атрибутов, которые могут использоваться, например, для добавления метаданных к функциям. Для получения и установки таких атрибутов используется обычная точка доступа к атрибутам. Обратите внимание, что текущая реализация поддерживает атрибуты функций только для функций, определённых пользователем. Атрибуты функций для встроенных функций могут быть добавлены в будущем.
Объект ячейки имеет атрибут
cell_contents. Его можно использовать для получения значения ячейки, а также для изменения значения.Дополнительную информацию об определении функции можно получить из её объекта кода; см. описание внутренних типов ниже. Тип
cellдоступен в модулеtypes. - Методы экземпляров
-
Объект метода экземпляра объединяет класс, экземпляр класса и любой вызываемый объект (обычно функцию, определённую пользователем).
Специальные атрибуты только для чтения:
__self__— это объект экземпляра класса,__func__— это объект функции;__doc__— это документация метода (такая же, как__func__.__doc__);__name__— имя метода (такое же, как__func__.__name__);__module__— имя модуля, в котором был определён метод, илиNoneесли недоступно.Методы также поддерживают доступ (но не изменение) произвольных атрибутов функции в базовом объекте функции.
Методы, определённые пользователем, могут создаваться при получении атрибута класса (возможно, через экземпляр этого класса), если этот атрибут является объектом функции, определённой пользователем, или объектом метода класса.
Когда объект метода экземпляра создаётся путём извлечения объекта функции, определённой пользователем, из класса через один из его экземпляров, атрибут
__self__этого объекта — экземпляр, и метод называется связанным. Атрибут__func__нового метода — это оригинальный объект функции.Когда объект метода экземпляра создаётся путём извлечения объекта метода класса из класса или экземпляра, атрибут
__self__этого объекта — сам класс, а атрибут__func__— объект функции, лежащий в основе метода класса.Когда вызывается объект метода экземпляра, базовая функция (
__func__) вызывается, вставляя экземпляр класса (__self__) в начало списка аргументов. Например, когдаC— это класс, содержащий определение функцииf(), иx— это экземплярC, вызовx.f(1)эквивалентен вызовуC.f(x, 1).Когда объект метода экземпляра получен от объекта метода класса, «экземпляр класса», хранящийся в
__self__, на самом деле будет сам классом, так что вызовx.f(1)илиC.f(1)эквивалентен вызовуf(C,1), гдеf— это основная функция.Обратите внимание, что преобразование объекта функции в объект метода экземпляра происходит каждый раз при получении атрибута из экземпляра. В некоторых случаях полезной оптимизацией является присвоение атрибута локальной переменной и вызов этой локальной переменной. Также обратите внимание, что это преобразование происходит только для функций, определённых пользователем; другие вызываемые объекты (и все невызываемые объекты) извлекаются без преобразования. Также важно отметить, что функции, определённые пользователем, которые являются атрибутами экземпляра класса, не преобразуются в связанные методы; это только происходит, когда функция является атрибутом класса.
- Генераторные функции
-
Функция или метод, использующий оператор
yield(см. раздел Оператор yield), называется генераторной функцией. Такая функция при вызове всегда возвращает объект итератора, который может быть использован для выполнения тела функции: вызов методаiterator.__next__()итератора заставит функцию выполняться до тех пор, пока она не вернёт значение с помощью оператораyield. Когда функция выполняет операторreturnили завершается, возникает исключениеStopIteration, и итератор достигнет конца набора возвращаемых значений. - Функции-генераторы
-
Функция или метод, определённые с помощью
async def, называются функциями-генераторами. При вызове такая функция возвращает объект генератора. Она может содержать выраженияawait, а также операторыasync withиasync for. Смотрите также раздел Объекты-генераторы. - Асинхронные генераторные функции
-
Функция или метод, определённый с помощью
async defи использующий операторyield, называется асинхронной генераторной функцией. При вызове такая функция возвращает объект асинхронного итератора, который может быть использован в оператореasync forдля выполнения тела функции.Вызов метода
aiterator.__anext__асинхронного итератора вернёт объект-задачу, который при ожидании выполнит функцию до тех пор, пока не вернёт значение с помощью выраженияyield. Когда функция выполняет пустой операторreturnили завершается, возникает исключениеStopAsyncIteration, и асинхронный итератор достигнет конца набора генерируемых значений. - Встроенные функции
-
Объект встроенной функции — это оболочка вокруг C-функции. Примеры встроенных функций —
len()иmath.sin()(math— стандартный встроенный модуль). Количество и тип аргументов определяются C-функцией. Специальные атрибуты только для чтения:__doc__— строка документации функции, илиNoneесли недоступна;__name__— имя функции;__self__установлено в значениеNone(но см. следующий пункт);__module__— имя модуля, в котором определена функция, илиNoneесли недоступно. - Встроенные методы
-
Это на самом деле другая форма встроенной функции, на этот раз содержащая объект, переданный C-функции в качестве неявного дополнительного аргумента. Пример встроенного метода —
alist.append(), предполагая, что alist — это объект списка. В этом случае специальный атрибут только для чтения__self__установлен в значение объекта, обозначенного alist. - Классы
-
Классы вызываемы. Эти объекты обычно действуют как фабрики для новых экземпляров самих себя, но возможны и варианты для типов классов, которые переопределяют
__new__(). Аргументы вызова передаются в__new__()и, в типичном случае, в__init__()для инициализации нового экземпляра. - Экземпляры классов
-
Экземпляры произвольных классов могут быть сделаны вызываемыми, определив метод
__call__()в их классе.
-
- Модули
-
Модули — это основные организационные единицы кода Python, и они создаются системой импорта системой импорта, которая вызывается либо оператором
import, либо путем вызова функций, таких какimportlib.import_module()и встроенной функцией__import__(). Объект модуля имеет пространство имен, реализованное объектом словаря (это тот словарь, к которому обращаются атрибуты функций, определенных в модуле). Обращения к атрибутам переводятся в поиск в этом словаре, например,m.xэквивалентноm.__dict__["x"]. Объект модуля не содержит объект кода, используемый для инициализации модуля (поскольку он не нужен после завершения инициализации).Присвоение атрибутов обновляет словарь пространства имен модуля, например,
m.x = 1эквивалентноm.__dict__["x"] = 1.Предопределённые (изменяемые) атрибуты:
__name__— имя модуля;__doc__— строка документации модуля, илиNoneесли недоступна;__annotations__(необязательно) — словарь, содержащий аннотации переменных, собранные во время выполнения тела модуля;__file__— путь к файлу, из которого был загружен модуль, если он загружен из файла. Атрибут__file__может отсутствовать для определённых типов модулей, например, C-модулей, статически связанных с интерпретатором; для модулей расширения, загружаемых динамически из общей библиотеки, это путь к файлу общей библиотеки.Специальный атрибут только для чтения:
__dict__— пространство имен модуля в виде объекта словаря.Подробность реализации CPython: Из-за того, как CPython очищает словари модулей, словарь модуля будет очищен, когда модуль выходит из области видимости, даже если в словаре есть активные ссылки. Чтобы избежать этого, скопируйте словарь или сохраните модуль во время прямого использования его словаря.
- Пользовательские классы
-
Типы пользовательских классов обычно создаются с помощью определений классов (см. раздел Определения классов). У класса есть пространство имен, реализованное в виде объекта словаря. Ссылка на атрибут класса преобразуется в поиск в этом словаре, например,
C.xпреобразуется вC.__dict__["x"](хотя существует ряд хуков, которые позволяют использовать другие способы поиска атрибутов). Если имя атрибута не найдено там, поиск атрибута продолжается в базовых классах. Этот поиск по базовым классам использует порядок разрешения методов C3, который работает корректно даже в присутствии структур наследования «ромба», где существуют несколько путей наследования, ведущих обратно к общему предку. Дополнительные сведения о порядке разрешения методов C3, используемом Python, можно найти в документации, прилагаемой к выпуску 2.3, по адресу https://www.python.org/download/releases/2.3/mro/.Когда ссылка на атрибут класса (для класса
C, скажем) даёт объект метода класса, он преобразуется в объект метода экземпляра, чьим атрибутом__self__являетсяC. Когда он даёт объект статического метода, он преобразуется в объект, заключённый в объекте статического метода. Подробнее о том, как атрибуты, полученные из класса, могут отличаться от тех, которые фактически содержатся в его__dict__, см. раздел Реализация дескрипторов.Присвоение атрибутов класса обновляет словарь класса, а не словарь базового класса.
Объект класса можно вызвать (см. выше), чтобы получить экземпляр класса (см. ниже).
Специальные атрибуты:
__name__— имя класса;__module__— имя модуля, в котором был определён класс;__dict__— словарь, содержащий пространство имен класса;__bases__— кортеж, содержащий базовые классы в порядке их появления в списке базовых классов;__doc__— строка документации класса, илиNoneесли не определена;__annotations__(необязательно) — словарь, содержащий аннотации переменных, собранные во время выполнения тела класса. - Экземпляры классов
-
Экземпляр класса создаётся путём вызова объекта класса (см. выше). Экземпляр класса имеет пространство имен, реализованное в виде словаря, который является первой областью поиска при обращении к атрибутам. Когда атрибут не найден там, и класс экземпляра имеет атрибут с таким именем, поиск продолжается с атрибутами класса. Если найденный атрибут класса является объектом пользовательской функции, он преобразуется в объект метода экземпляра, чьим атрибутом
__self__является экземпляр. Объекты статических методов и методов класса также преобразуются; см. выше в разделе «Классы». Подробнее о других способах, с помощью которых атрибуты класса, получаемые через экземпляры, могут отличаться от объектов, фактически хранящихся в__dict__класса, см. раздел Реализация дескрипторов. Если атрибут класса не найден, и у класса объекта есть метод__getattr__(), он вызывается для удовлетворения поиска.Присвоение и удаление атрибутов обновляют словарь экземпляра, а не словарь класса. Если класс имеет метод
__setattr__()или__delattr__(), он вызывается вместо прямого обновления словаря экземпляра.Экземпляры класса могут имитировать числа, последовательности или отображения, если у них есть методы с определёнными специальными именами. См. раздел Специальные имена методов.
Специальные атрибуты:
__dict__— словарь атрибутов;__class__— класс экземпляра. - Объекты ввода-вывода (также известные как объекты файлов)
-
Объект файлового объекта представляет собой открытый файл. Доступны различные сокращения для создания объектов файлов: встроенная функция
open(), а такжеos.popen(),os.fdopen()и методmakefile()объектов сокета (и, возможно, другие функции или методы, предоставляемые модулями расширения).Объекты
sys.stdin,sys.stdoutиsys.stderrинициализированы файловыми объектами, соответствующими стандартным потокам ввода, вывода и ошибок интерпретатора; все они открыты в текстовом режиме и, следовательно, следуют интерфейсу, определённому абстрактным классомio.TextIOBase. - Внутренние типы
-
Некоторые типы, используемые интерпретатором внутри, доступны пользователю. Их определения могут измениться в будущих версиях интерпретатора, но они упомянуты здесь для полноты.
- Объекты кода
-
Объекты кода представляют собой скомпилированный байт-код исполняемый Python-код или байт-код. Разница между объектом кода и объектом функции заключается в том, что объект функции содержит явную ссылку на глобальные переменные функции (модуль, в котором она была определена), а объект кода не содержит контекста; также значения аргументов по умолчанию хранятся в объекте функции, а не в объекте кода (потому что они представляют значения, вычисленные во время выполнения). В отличие от объектов функций, объекты кода неизменяемы и не содержат ссылок (прямых или косвенных) на изменяемые объекты.
Специальные атрибуты для чтения:
co_nameуказывает имя функции;co_argcount— общее количество позиционных аргументов (включая позиционные-только аргументы и аргументы с значениями по умолчанию);co_posonlyargcount— количество позиционных-только аргументов (включая аргументы с значениями по умолчанию);co_kwonlyargcount— количество аргументов только по ключевому слову (включая аргументы с значениями по умолчанию);co_nlocals— количество локальных переменных, используемых функцией (включая аргументы);co_varnames— кортеж, содержащий имена локальных переменных (начиная с имён аргументов);co_cellvars— кортеж, содержащий имена локальных переменных, на которые ссылаются вложенные функции;co_freevars— кортеж, содержащий имена свободных переменных;co_code— строка, представляющая последовательность инструкций байт-кода;co_consts— кортеж, содержащий литералы, используемые байт-кодом;co_names— кортеж, содержащий имена, используемые байт-кодом;co_filename— имя файла, из которого был скомпилирован код;co_firstlineno— номер первой строки функции;co_lnotab— строка, кодирующая отображение смещений байт-кода на номера строк (подробнее см. исходный код интерпретатора);co_stacksize— необходимый размер стека;co_flags— целое число, кодирующее набор флагов для интерпретатора.Для
co_flagsопределены следующие биты флагов: бит0x04установлен, если функция использует синтаксис*arguments, чтобы принять произвольное количество позиционных аргументов; бит0x08установлен, если функция использует синтаксис**keywords, чтобы принять произвольные аргументы по ключевым словам; бит0x20установлен, если функция является генератором.Декларации будущих функций (
from __future__ import division) также используют биты вco_flags, чтобы указать, был ли объект кода скомпилирован с включённой определённой функцией: бит0x2000установлен, если функция была скомпилирована с включённым режимом деления по правилам будущего; биты0x10и0x1000использовались в более ранних версиях Python.Другие биты в
co_flagsзарезервированы для внутреннего использования.Если объект кода представляет функцию, первый элемент в
co_consts— строка документации функции, илиNoneпри её отсутствии.
- Объекты фреймов
-
Объекты фреймов представляют кадр выполнения. Они могут встречаться в объектах отслеживания (см. ниже), а также передаются зарегистрированным функциям отслеживания.
Специальные атрибуты для чтения:
f_back— предыдущий кадр стека (в сторону вызывающей функции) илиNone— если это самый нижний кадр стека;f_code— объект кода, выполняемый в этом кадре;f_locals— словарь для поиска локальных переменных;f_globalsиспользуется для глобальных переменных;f_builtinsиспользуется для встроенных (внутренних) имён;f_lastiуказывает точную инструкцию (это индекс в строке байт-кода объекта кода).Обращение к
f_codeвызывает событие отслеживания отслеживанияobject.__getattr__с аргументамиobjи"f_code".Специальные изменяемые атрибуты:
f_trace, если неNone, — функция, вызываемая для различных событий во время выполнения кода (используется отладчиком). Обычно событие срабатывает для каждой новой строки исходного кода — это можно отключить, установивf_trace_linesвFalse.Реализации могут позволять запрашивать события по каждой инструкции, установив
f_trace_opcodesвTrue. Обратите внимание, что это может привести к неопределённому поведению интерпретатора, если исключения, поднятые функцией отслеживания, выйдут за пределы отслеживаемой функции.f_lineno— текущий номер строки кадра — запись в него изнутри функции отслеживания переходит на указанную строку (только для самого нижнего кадра). Отладчик может реализовать команду Переход (также известную как Установить следующую инструкцию) путём записи в f_lineno.Объекты фреймов поддерживают один метод:
-
frame.clear() -
Этот метод очищает все ссылки на локальные переменные, удерживаемые кадром. Кроме того, если кадр принадлежал генератору, генератор завершается. Это помогает прервать циклы ссылок, включающие объекты фреймов (например, при перехвате исключения и сохранении его стека вызовов для последующего использования).
RuntimeErrorподнимается, если кадр выполняется в данный момент.Введено в версии 3.4.
-
- Объекты отслеживания
-
Объекты отслеживания представляют стек вызовов исключения. Объект отслеживания неявно создаётся при возникновении исключения и может также быть явно создан вызовом
types.TracebackType.Для неявно созданных стеков вызовов, когда поиск обработчика исключений разворачивает стек выполнения, на каждом уровне разворачивания в стек вставляется объект отслеживания перед текущим стеком вызовов. Когда вводится обработчик исключения, стек вызовов становится доступным программе. (См. раздел Оператор try.) Он доступен как третий элемент кортежа, возвращаемого
sys.exc_info(), и как атрибут__traceback__перехваченного исключения.Когда в программе нет подходящего обработчика, стек вызовов записывается (в красивом формате) в стандартный поток ошибок; если интерпретатор интерактивный, он также становится доступным пользователю как
sys.last_traceback.Для явно созданных стеков вызовов от создателя стека вызовов зависит, как атрибуты
tb_nextдолжны быть связаны, чтобы образовать полный стек вызовов.Специальные атрибуты для чтения:
tb_frameуказывает на кадр выполнения текущего уровня;tb_linenoуказывает номер строки, где произошло исключение;tb_lastiуказывает точную инструкцию. Номер строки и последняя инструкция в стеке вызовов могут отличаться от номера строки объекта кадра, если исключение произошло в оператореtryбез соответствующего блока except или с блоком finally.Обращение к
tb_frameвызывает событие отслеживания отслеживанияobject.__getattr__с аргументамиobjи"tb_frame".Специальный изменяемый атрибут:
tb_next— следующий уровень в стеке вызовов (в сторону кадра, где произошло исключение) илиNone— если следующего уровня нет.Изменено в версии 3.7: Объекты отслеживания теперь можно явно создавать из Python-кода, и атрибут
tb_nextсуществующих экземпляров можно обновлять. - Объекты срезов
-
Объекты срезов используются для представления срезов для методов
__getitem__(). Они также создаются встроенной функциейslice().Специальные атрибуты для чтения:
start— нижняя граница;stop— верхняя граница;step— значение шага; каждое из них —Noneпри отсутствии. Эти атрибуты могут иметь любой тип.Объекты срезов поддерживают один метод:
-
slice.indices(self, length) -
Этот метод принимает единственный целочисленный аргумент length и вычисляет информацию о срезе, который описывает объект среза, если он применяется к последовательности из length элементов. Он возвращает кортеж из трёх целых чисел; соответственно, это start и stop индексы и step или длина шага среза. Пропущенные или вне диапазона индексы обрабатываются так же, как обычные срезы.
-
- Объекты статических методов
-
Объекты статических методов предоставляют способ обойти преобразование объектов функций в объекты методов, описанное выше. Объект статического метода — оболочка вокруг любого другого объекта, обычно объекта метода, определённого пользователем. Когда объект статического метода извлекается из класса или экземпляра класса, возвращаемым объектом фактически является обернутый объект, который не подвергается дальнейшему преобразованию. Объекты статических методов сами по себе не вызываемы, хотя объекты, которые они оборачивают, обычно вызываемы. Объекты статических методов создаются встроенным конструктором
staticmethod(). - Объекты методов класса
-
Объект метода класса, подобно объекту статического метода, — оболочка вокруг другого объекта, которая изменяет способ, которым этот объект извлекается из классов и экземпляров классов. Поведение объектов методов класса при таком извлечении описывается выше, в разделе «Методы, определённые пользователем». Объекты методов класса создаются встроенным конструктором
classmethod().
3.3. Имена специальных методов
Класс может реализовывать определенные операции, вызываемые с помощью специального синтаксиса (например, арифметические операции или индексирование и срезы), определением методов со специальными именами. Это подход Python к перегрузке операторов, позволяющий классам определять собственное поведение по отношению к операторам языка. Например, если класс определяет метод с именем __getitem__(), и x — это экземпляр этого класса, то x[i] примерно эквивалентно type(x).__getitem__(x, i). За исключением случаев, когда это упоминается, попытка выполнить операцию приводит к исключению, когда нет соответствующего определенного метода (обычно AttributeError или TypeError).
Установление специального метода в None указывает на то, что соответствующая операция недоступна. Например, если класс устанавливает __iter__() в None, класс не является итерируемым, поэтому вызов iter() для его экземпляров вызовет TypeError (без обратного вызова __getitem__()). 2
При реализации класса, эмулирующего любой встроенный тип, важно, чтобы эмуляция реализовывалась только в той степени, в которой это имеет смысл для моделируемого объекта. Например, некоторые последовательности могут хорошо работать с извлечением отдельных элементов, но извлечение среза может быть бессмысленным. (Один пример этого — интерфейс NodeList в модели объекта документа W3C.)
3.3.1. Основные настройки
-
object.__new__(cls[, ...]) -
Вызывается для создания нового экземпляра класса cls.
__new__()— это статический метод (специальный случай, поэтому вам не нужно его объявлять как таковой), который принимает в качестве первого аргумента класс, для которого запрашивается экземпляр. Остальные аргументы — те, которые переданы в выражение конструктора объекта (вызов класса). Значение, возвращаемое__new__(), должно быть новым экземпляром объекта (обычно экземпляром cls).Типичные реализации создают новый экземпляр класса, вызывая метод
__new__()суперкласса с использованиемsuper().__new__(cls[, ...])с соответствующими аргументами, а затем, при необходимости, модифицируют созданный экземпляр перед его возвратом.Если
__new__()вызывается во время создания объекта и возвращает экземпляр cls, то метод__init__()нового экземпляра будет вызван, как__init__(self[, ...]), где self — новый экземпляр, а остальные аргументы — те же, что были переданы в конструктор объекта.Если
__new__()не возвращает экземпляр cls, то метод__init__()нового экземпляра не будет вызван.__new__()предназначен в основном для того, чтобы подклассы неизменяемых типов (например, int, str или tuple) могли настраивать создание экземпляров. Также он часто переопределяется в пользовательских метаклассах для настройки создания классов.
-
object.__init__(self[, ...]) -
Вызывается после того, как экземпляр был создан (
__new__()), но перед его возвратом вызывающей стороне. Аргументы — те, которые переданы в выражение конструктора класса. Если базовый класс имеет метод__init__(), метод__init__()производного класса, если таковой имеется, должен явно его вызвать, чтобы обеспечить правильную инициализацию части базового класса экземпляра; например:super().__init__([args...]).Поскольку
__new__()и__init__()работают вместе при создании объектов (__new__()создает его, а__init__()его настраивает), метод__init__()не должен возвращать никакого значения, отличного отNone; в противном случае во время выполнения будет поднято исключениеTypeError.
-
object.__del__(self) -
Вызывается, когда экземпляр собирается быть уничтожен. Это также называется финализатором или (неправильно) деструктором. Если базовый класс имеет метод
__del__(), метод__del__()производного класса, если таковой имеется, должен явно его вызвать, чтобы обеспечить правильное удаление части базового класса экземпляра.Возможен (хотя и не рекомендуется!) случай, когда метод
__del__()откладывает уничтожение экземпляра, создавая новую ссылку на него. Это называется возрождением объекта. Зависит от реализации, будет ли__del__()вызываться второй раз, когда возрожденный объект собирается быть уничтожен; текущая реализация CPython вызывает его только один раз.Не гарантируется, что методы
__del__()вызываются для объектов, которые всё ещё существуют при выходе интерпретатора.Примечание
del xне напрямую вызываетx.__del__()— первый декрементирует счетчик ссылок дляxна единицу, а второй вызывается только тогда, когда счетчик ссылокxдостигает нуля.Подробность реализации CPython: Возможно, что цикл ссылок предотвратит уменьшение счетчика ссылок объекта до нуля. В этом случае цикл будет обнаружен и удален позже сборщиком мусора циклов. Распространённой причиной циклов ссылок является перехват исключения в локальной переменной. Локальные переменные фрейма затем ссылаются на исключение, которое ссылается на свой собственный стек вызовов, который ссылается на локальные переменные всех фреймов, перехваченных в стеке вызовов.
См. также
Документацию для модуля
gc.Предупреждение
Из-за нестабильных обстоятельств вызова методов
__del__()исключения, возникающие во время их выполнения, игнорируются, и вместо этого вsys.stderrвыводится предупреждение. В частности:-
Метод
__del__()может быть вызван во время выполнения произвольного кода, включая любой произвольный поток. Если__del__()нужно взять блокировку или вызвать любой другой блокирующий ресурс, он может заблокироваться, так как этот ресурс может быть уже занят кодом, прерванным для выполнения__del__(). -
Метод
__del__()может выполняться во время завершения работы интерпретатора. В результате глобальные переменные, к которым ему нужно получить доступ (включая другие модули), могут уже быть удалены или установлены вNone. Python гарантирует, что глобальные переменные, имена которых начинаются с одного символа подчёркивания, удаляются из своего модуля перед удалением других глобальных переменных; если других ссылок на такие глобальные переменные не существует, это может помочь в обеспечении того, что импортированные модули всё ещё доступны в момент вызова метода__del__().
-
Метод
-
object.__repr__(self) -
Вызывается функцией
repr()для вычисления «официального» строкового представления объекта. По возможности, это должно выглядеть как допустимое выражение Python, которое можно использовать для повторного создания объекта с тем же значением (при соответствующей среде). Если это невозможно, следует вернуть строку вида<...some useful description...>. Возвращаемое значение должно быть строковым объектом. Если класс определяет__repr__(), но не__str__(), то__repr__()также используется, когда требуется «неофициальное» строковое представление экземпляров этого класса.Это обычно используется для отладки, поэтому важно, чтобы представление было информативным и однозначным.
-
object.__str__(self) -
Вызывается
str(object)и встроенными функциямиformat()иprint()для вычисления «неофициального» или удобного для печати строкового представления объекта. Возвращаемое значение должно быть строковым объектом.Этот метод отличается от
object.__repr__()тем, что нет ожидания, что__str__()вернёт допустимое выражение Python: можно использовать более удобное или краткое представление.По умолчанию, реализация, определенная встроенным типом
object, вызываетobject.__repr__().
-
object.__format__(self, format_spec) -
Вызывается встроенной функцией
format(), а также, в частности, при вычислении форматированных строковых литералов и методаstr.format()для получения «форматированного» строкового представления объекта. Аргумент format_spec — это строка, содержащая описание желаемых параметров форматирования. Интерпретация аргумента format_spec зависит от типа, реализующего__format__(), однако большинство классов либо делегируют форматирование одному из встроенных типов, либо используют аналогичный синтаксис форматирования.См. Мини-язык спецификаций форматирования для описания стандартного синтаксиса форматирования.
Возвращаемое значение должно быть объектом строки.
Изменено в версии 3.4: Метод __format__ класса
objectсам вызывает исключениеTypeError, если ему передана любая непустая строка.Изменено в версии 3.7:
object.__format__(x, '')теперь эквивалентенstr(x), а неformat(str(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__()для важных замечаний по созданию хешируемых объектов, которые поддерживают пользовательские операции сравнения и могут использоваться в качестве ключей словарей.Нет версий этих методов с переставленными аргументами (которые необходимо использовать, когда левый аргумент не поддерживает операцию, но правый аргумент ее поддерживает); скорее,
__lt__()и__gt__()являются отражением друг друга,__le__()и__ge__()являются отражением друг друга, а__eq__()и__ne__()— отражение самих себя. Если операнды разных типов, и тип правого операнда является прямым или косвенным подклассом типа левого операнда, приоритет имеет отражённый метод правого операнда, в противном случае приоритет имеет метод левого операнда. Виртуальное наследование не учитывается.
-
object.__hash__(self) -
Вызывается встроенной функцией
hash()и для операций над членами хэшируемых коллекций, включаяset,frozensetиdict. Метод__hash__()должен возвращать целое число. Единственное необходимое свойство — объекты, сравнимые как равные, должны иметь одинаковое значение хэша; рекомендуется смешивать значения хэшей компонентов объекта, которые также участвуют в сравнении объектов, упаковывая их в кортеж и хэшируя кортеж. Пример:def __hash__(self): return hash((self.name, self.nick, self.color))Примечание
hash()обрезает значение, возвращаемое пользовательским методом хэширования объекта__hash__(), до размераPy_ssize_t. Как правило, это 8 байт на 64-битных сборках и 4 байта на 32-битных. Если хэш объекта__hash__()должен работать на сборках с разной разрядностью, убедитесь, что вы проверяете ширину на всех поддерживаемых сборках. Простое решение —python -c "import sys; print(sys.hash_info.width)".Если класс не определяет метод
__eq__(), он не должен определять и операцию__hash__(); если он определяет__eq__(), но не__hash__(), его экземпляры нельзя использовать в качестве элементов хэшируемых коллекций. Если класс определяет изменяемые объекты и реализует метод__eq__(), он не должен реализовывать__hash__(), так как реализация хэшируемых коллекций требует, чтобы значение хэша ключа было неизменяемым (если значение хэша объекта изменяется, он окажется в неправильном хэш-бакете).Пользовательские классы по умолчанию имеют методы
__eq__()и__hash__(); с ними все объекты считаются неравными (кроме самих себя) иx.__hash__()возвращает соответствующее значение, такое, чтоx == yподразумевает какx is y, так иhash(x) == hash(y).Класс, переопределяющий
__eq__()и не определяющий__hash__(), будет иметь свой__hash__()неявным образом установлен наNone. Когда метод__hash__()классаNone, экземпляры класса будут генерировать соответствующее исключениеTypeErrorпри попытке получить их значение хэша и также будут правильно определяться как нехэшируемые при проверкеisinstance(obj, collections.abc.Hashable).Если класс, переопределяющий
__eq__(), должен сохранить реализацию__hash__()из родительского класса, интерпретатор должен быть об этом явно проинформирован, установив__hash__ = <ParentClass>.__hash__.Если класс, не переопределяющий
__eq__(), хочет подавить поддержку хэширования, он должен включить__hash__ = Noneв определение класса. Класс, который определяет собственный__hash__()и явным образом генерируетTypeError, будет ошибочно определён как хэшируемый вызовомisinstance(obj, collections.abc.Hashable).Примечание
По умолчанию значения хэша объектов str и bytes «засаливаются» случайным значением, непредсказуемым при разных запусках интерпретатора Python в одном и том же процессе.
Это призвано защитить от атаки типа отказ в обслуживании, вызванной специально подобранными входными данными, которые эксплуатируют худший случай производительности вставки в словарь, сложность O(n2). Подробности см. в http://www.ocert.org/advisories/ocert-2011-003.html.
Изменение значений хэша влияет на порядок итерации множеств. Python никогда не давал гарантий о порядке итерации (а он, как правило, отличается на 32-битных и 64-битных сборках).
См. также
PYTHONHASHSEED.Изменено в версии 3.3: Случайное хэширование включено по умолчанию.
-
object.__bool__(self) -
Вызывается для реализации проверки истинности и встроенной операции
bool(); должен возвращатьFalseилиTrue. Если этот метод не определен, вызывается__len__(), если он определен, и объект считается истинным, если его результат отличен от нуля. Если класс не определяет ни__len__(), ни__bool__(), все его экземпляры считаются истинными.
3.3.2. Настройка доступа к атрибутам
Следующие методы можно определить, чтобы настроить поведение доступа к атрибутам (использования, присваивания или удаления x.name) для экземпляров класса.
-
object.__getattr__(self, name) -
Вызывается, когда стандартный доступ к атрибуту завершается ошибкой
AttributeError(либо__getattribute__()вызываетAttributeError, потому что имя не является атрибутом экземпляра или атрибутом в дереве класса дляself; либо__get__()свойства имя вызываетAttributeError). Этот метод должен либо вернуть (вычисленное) значение атрибута, либо вызвать исключениеAttributeError.Обратите внимание, что если атрибут найден обычным способом,
__getattr__()не вызывается. (Это преднамеренная асимметрия между__getattr__()и__setattr__().) Это сделано как для повышения эффективности, так и потому, что в противном случае__getattr__()не смог бы получить доступ к другим атрибутам экземпляра. Обратите внимание, что, по крайней мере, для переменных экземпляра можно имитировать полный контроль, не вставляя значения в словарь атрибутов экземпляра (а вместо этого вставляя их в другой объект). См. метод__getattribute__()ниже для способа фактического получения полного контроля над доступом к атрибутам.
-
object.__getattribute__(self, name) -
Безусловно вызывается для реализации доступа к атрибутам экземпляров класса. Если класс также определяет
__getattr__(), последний не будет вызван, если__getattribute__()не вызовет его явно или не подниметAttributeError. Этот метод должен вернуть (вычисленное) значение атрибута или вызвать исключениеAttributeError. Чтобы избежать бесконечной рекурсии в этом методе, его реализация должна всегда вызывать метод базового класса с тем же именем для доступа к любым необходимым атрибутам, например,object.__getattribute__(self, name).Примечание
Этот метод все еще может быть обойден при поиске специальных методов в результате неявного вызова через синтаксис языка или встроенные функции. См. Поиск специальных методов.
Для определенных чувствительных доступов к атрибутам генерирует событие аудита аудита
object.__getattr__с аргументамиobjиname.
-
object.__setattr__(self, name, value) -
Вызывается при попытке присваивания атрибута. Вызывается вместо стандартного механизма (т.е. сохранение значения в словаре экземпляра). имя — имя атрибута, значение — значение, которое ему нужно присвоить.
Если
__setattr__()хочет присвоить значение атрибуту экземпляра, он должен вызвать метод базового класса с тем же именем, например,object.__setattr__(self, name, value).Для определенных чувствительных присваиваний атрибутов генерирует событие аудита аудита
object.__setattr__с аргументамиobj,name,value.
-
object.__delattr__(self, name) -
Подобно
__setattr__(), но для удаления атрибута вместо присваивания. Это следует реализовывать только в том случае, еслиdel obj.nameимеет смысл для объекта.Для определенных чувствительных удалений атрибутов генерирует событие аудита аудита
object.__delattr__с аргументамиobjиname.
-
object.__dir__(self) -
Вызывается при вызове
dir()для объекта. Должна быть возвращена последовательность.dir()преобразует возвращаемую последовательность в список и сортирует его.
3.3.2.1. Настройка доступа к атрибутам модуля
Специальные имена __getattr__ и __dir__ также могут использоваться для настройки доступа к атрибутам модуля. Функция __getattr__ на уровне модуля должна принимать один аргумент — имя атрибута — и возвращать вычисленное значение или вызывать исключение AttributeError. Если атрибут не найден в объекте модуля через обычный поиск, т.е. object.__getattribute__(), то __getattr__ ищется в модуле __dict__ прежде чем поднимать AttributeError. Если найден, он вызывается с именем атрибута, и результат возвращается.
Функция __dir__ не должна принимать аргументы и возвращать последовательность строк, представляющих доступные имена в модуле. Если присутствует, эта функция переопределяет стандартный поиск dir() в модуле.
Для более тонкой настройки поведения модуля (установка атрибутов, свойств и т.д.) можно установить атрибут __class__ объекта модуля в подкласс types.ModuleType. Например:
import sys
from types import ModuleType
class VerboseModule(ModuleType):
def __repr__(self):
return f'Verbose {self.__name__}'
def __setattr__(self, attr, value):
print(f'Setting {attr}...')
super().__setattr__(attr, value)
sys.modules[__name__].__class__ = VerboseModule
Примечание
Определение модуля __getattr__ и установка модуля __class__ влияют только на поиск, выполненный с использованием синтаксиса доступа к атрибутам — прямой доступ к глобальным переменным модуля (как с кода внутри модуля, так и через ссылку на словарь глобальных переменных модуля) не затрагивается.
Изменено в версии 3.5: __class__ атрибут модуля теперь может изменяться.
Добавлен в версии 3.7: __getattr__ и __dir__ атрибуты модуля.
См. также
- PEP 562 - Модули __getattr__ и __dir__
-
Описание функций
__getattr__и__dir__для модулей.
3.3.2.2. Реализация дескрипторов
Следующие методы применяются только тогда, когда экземпляр класса, содержащего метод (так называемый класс-дескриптор), появляется в владельце классе (дескриптор должен быть либо в словаре класса владельца, либо в словаре класса, являющегося одним из его предков). В примерах ниже, «атрибут» относится к атрибуту, имя которого является ключом свойства в __dict__ классе владельца.
-
object.__get__(self, instance, owner=None) -
Вызывается для получения атрибута класса-владельца (доступ к классовому атрибуту) или экземпляра этого класса (доступ к экземпляру атрибута). Необязательный аргумент owner — это класс-владелец, а instance — экземпляр, через который был получен доступ к атрибуту, или
Noneкогда к атрибуту обращаются через owner.Этот метод должен возвращать вычисленное значение атрибута или возбуждать исключение
AttributeError.PEP 252 указывает, что
__get__()может вызываться с одним или двумя аргументами. Собственные встроенные дескрипторы Python поддерживают это спецификацию; однако, вероятно, некоторые сторонние инструменты имеют дескрипторы, которым требуются оба аргумента. Собственная реализация__getattribute__()Python всегда передает оба аргумента, независимо от того, требуются они или нет.
-
object.__set__(self, instance, value) -
Вызывается для установки атрибута на экземпляр instance класса-владельца в новое значение value.
Обратите внимание, что добавление
__set__()или__delete__()изменяет тип дескриптора на «дескриптор данных». Дополнительные сведения см. в разделе Вызов дескрипторов.
-
object.__delete__(self, instance) -
Вызывается для удаления атрибута из экземпляра instance класса-владельца.
-
object.__set_name__(self, owner, name) -
Вызывается в момент создания класса-владельца owner. Дескриптор был назначен имени name.
Примечание
__set_name__()вызывается только неявно как часть конструктораtype, поэтому его необходимо вызывать явно с соответствующими параметрами при добавлении дескриптора в класс после его первоначального создания:class A: pass descr = custom_descriptor() A.attr = descr descr.__set_name__(A, 'attr')
Дополнительные сведения см. в разделе Создание объекта класса.
Введено в версии 3.6.
Атрибут __objclass__ интерпретируется модулем inspect как указывающий на класс, где был определен этот объект (правильное задание этого атрибута может помочь в интроспекции атрибутов динамических классов во время выполнения). Для вызываемых объектов это может указывать на то, что в качестве первого позиционного аргумента ожидается или требуется экземпляр заданного типа (или подкласса) (например, CPython задает этот атрибут для несвязанных методов, реализованных на C).
3.3.2.3. Вызов дескрипторов
В общем случае, дескриптор — это атрибут объекта с «поведением привязки», чья обработка доступа к атрибуту была переопределена методами протокола дескрипторов: __get__(), __set__() и __delete__(). Если для объекта определены какие-либо из этих методов, он считается дескриптором.
По умолчанию доступ к атрибуту осуществляется получение, установка или удаление атрибута из словаря объекта. Например, a.x имеет цепочку поиска, начинающуюся с a.__dict__['x'], затем type(a).__dict__['x'], и продолжающуюся через базовые классы type(a), исключая метаклассы.
Однако, если найденное значение — это объект, определяющий один из методов дескриптора, Python может переопределить стандартное поведение и вызвать метод дескриптора вместо этого. Место, где это происходит в цепочке приоритетов, зависит от определенных методов дескриптора и способа их вызова.
Точка входа для вызова дескриптора — это привязка, a.x. Способ сборки аргументов зависит от a:
- Прямой вызов
-
Простейший и наименее распространенный вызов — когда пользовательский код непосредственно вызывает метод дескриптора:
x.__get__(a). - Привязка к экземпляру
-
Если привязка к экземпляру объекта,
a.xпреобразуется в вызов:type(a).__dict__['x'].__get__(a, type(a)). - Привязка к классу
-
Если привязка к классу,
A.xпреобразуется в вызов:A.__dict__['x'].__get__(None, A). - Привязка super
-
Если
aявляется экземпляромsuper, то привязкаsuper(B, obj).m()ищетobj.__class__.__mro__базовый классAнепосредственно послеBи вызывает дескриптор с вызовом:A.__dict__['m'].__get__(obj, obj.__class__).
Для привязок к экземплярам приоритет вызова дескриптора зависит от определенных методов дескриптора. Дескриптор может определять любую комбинацию __get__(), __set__() и __delete__(). Если он не определяет __get__(), то обращение к атрибуту вернет сам объект дескриптора, если только в словаре экземпляра объекта нет значения. Если дескриптор определяет __set__() и/или __delete__(), он является дескриптором данных; если ни то, ни другое не определено, он является дескриптором без данных. Обычно дескрипторы данных определяют как __get__(), так и __set__(), в то время как дескрипторы без данных имеют только метод __get__(). Дескрипторы данных с определенными __get__() и __set__() (и/или __delete__()) всегда переопределяют переопределение в словаре экземпляра. В отличие от этого, дескрипторы без данных могут быть переопределены экземплярами.
Методы Python (включая те, которые помечены декораторами @staticmethod и @classmethod) реализованы как дескрипторы без данных. Соответственно, экземпляры могут переопределять и изменять поведение методов. Это позволяет отдельным экземплярам приобретать поведение, отличное от поведения других экземпляров того же класса.
Функция property() реализована как дескриптор данных. Соответственно, экземпляры не могут переопределить поведение свойства.
3.3.2.4. __slots__
__slots__ позволяют явно объявлять данные члены (например, свойства) и запрещать создание __dict__ и __weakref__ (если они не объявлены явно в __slots__ или доступны в родительском классе).
Экономия памяти при использовании __dict__ может быть значительной. Скорость поиска атрибутов также может быть значительно улучшена.
-
object.__slots__ -
Эта переменная класса может принимать строку, итерируемый объект или последовательность строк с именами переменных, используемых экземплярами. __slots__ резервирует место для объявленных переменных и предотвращает автоматическое создание
__dict__и __weakref__ для каждого экземпляра.
3.3.2.4.1. Примечания по использованию __slots__
- При наследовании от класса без __slots__ атрибут
__dict__и __weakref__ экземпляров всегда будут доступны. - Без переменной
__dict__экземплярам нельзя назначать новые переменные, не перечисленные в определении __slots__. Попытка присвоить значение неопределенной переменной приводит к ошибкеAttributeError. Если требуется динамическое назначение новых переменных, добавьте'__dict__'в последовательность строк в объявлении __slots__. - Без переменной __weakref__ для каждого экземпляра классы, определяющие __slots__, не поддерживают
weak referencesк своим экземплярам. Если нужна поддержка слабых ссылок, добавьте'__weakref__'в последовательность строк в объявлении __slots__. - __slots__ реализуются на уровне класса путём создания дескрипторов для каждого имени переменной. В результате атрибуты класса нельзя использовать для установки значений по умолчанию для переменных экземпляров, определённых с помощью __slots__; в противном случае атрибут класса перезапишет назначение дескриптора.
- Действие объявления __slots__ не ограничивается классом, в котором оно определено. __slots__, объявленные в родительских классах, доступны в дочерних классах. Однако дочерние подклассы получат
__dict__и __weakref__, если они также не определят __slots__ (которые должны содержать только имена дополнительных слотов). - Если класс определяет слот, также определённый в базовом классе, переменная экземпляра, определённая слотом базового класса, недоступна (кроме получения его дескриптора напрямую из базового класса). Это делает значение программы неопределённым. В будущем может быть добавлена проверка для предотвращения этого.
- Непустые __slots__ не работают для классов, производных от «встроенных типов переменной длины», таких как
int,bytesиtuple. - Любой нестроковый итерируемый объект может быть присвоен __slots__.
- Если используется словарь
dictionaryдля присвоения __slots__, ключи словаря будут использоваться как имена слотов. Значения словаря могут быть использованы для предоставления строковых описаний атрибутов, которые будут распознаныinspect.getdoc()и отображены в выводеhelp(). -
Присвоение
__class__работает только в том случае, если у обоих классов одинаковые __slots__. -
Множественное наследование с несколькими родительскими классами со слотами может быть использовано, но только один родитель может иметь атрибуты, созданные слотами (другие базовые классы должны иметь пустые макеты слотов) - нарушения приведут к ошибке
TypeError. - Если в качестве __slots__ используется итератор, то для каждого значения итератора создается дескриптор. Однако атрибут __slots__ будет пустым итератором.
3.3.3. Настройка создания классов
Всякий раз, когда класс наследуется от другого класса, метод __init_subclass__() вызывается в родительском классе. Таким образом, можно создавать классы, которые изменяют поведение подклассов. Это тесно связано с декораторами классов, но если декораторы классов влияют только на конкретный класс, к которому они применяются, то __init_subclass__ применяется только к будущим подклассам класса, определяющего метод.
-
classmethod object.__init_subclass__(cls) -
Этот метод вызывается всякий раз, когда содержащий класс становится подклассом. Тогда cls — это новый подкласс. Если он определен как обычный метод экземпляра, этот метод неявно преобразуется в метод класса.
Ключевые аргументы, которые передаются новому классу, передаются в родительский класс
__init_subclass__. Для совместимости с другими классами, использующими__init_subclass__, следует извлечь необходимые ключевые аргументы и передать остальные в базовый класс, как в примере:class Philosopher: def __init_subclass__(cls, /, default_name, **kwargs): super().__init_subclass__(**kwargs) cls.default_name = default_name class AustralianPhilosopher(Philosopher, default_name="Bruce"): passРеализация по умолчанию
object.__init_subclass__ничего не делает, но вызывает ошибку, если вызывается с любыми аргументами.Примечание
Подсказка метакласса
metaclassиспользуется остальной частью механизма типов и никогда не передаётся в реализации__init_subclass__. Фактический метакласс (а не явная подсказка) может быть получен какtype(cls).Новое в версии 3.6.
3.3.3.1. Метаклассы
По умолчанию классы создаются с помощью type(). Тело класса выполняется в новом пространстве имён, и имя класса привязывается локально к результату type(name, bases, namespace).
Процесс создания класса можно настроить, передав ключевой аргумент metaclass в строке определения класса или унаследовав от существующего класса, включающего такой аргумент. В следующем примере MyClass и MySubclass являются экземплярами Meta:
class Meta(type):
pass
class MyClass(metaclass=Meta):
pass
class MySubclass(MyClass):
pass
Любые другие ключевые аргументы, указанные в определении класса, передаются во все операции метакласса, описанные ниже.
При выполнении определения класса происходят следующие шаги:
- Разрешаются записи MRO;
- определяется соответствующий метакласс;
- подготавливается пространство имен класса;
- выполняется тело класса;
- создаётся объект класса.
3.3.3.2. Разрешение записей MRO
Если базовый элемент, который появляется в определении класса, не является экземпляром type, то на нём ищется метод __mro_entries__. Если он найден, он вызывается с кортежем исходных базовых элементов. Этот метод должен вернуть кортеж классов, которые будут использоваться вместо этого базового элемента. Кортеж может быть пустым, в этом случае исходный базовый элемент игнорируется.
См. также
PEP 560 — Основная поддержка модуля типов и типов-обобщений
3.3.3.3. Определение подходящего метакласса
Подходящий метакласс для определения класса определяется следующим образом:
- если нет базовых элементов и нет явного метакласса, то используется
type(); - если задан явный метакласс и он не является экземпляром
type(), то он используется непосредственно как метакласс; - если задан экземпляр
type()в качестве явного метакласса или определены базовые элементы, используется наиболее производный метакласс.
Наиболее производный метакласс выбирается из явно указанного метакласса (если таковой имеется) и метаклассов (т.е. type(cls)) всех указанных базовых классов. Наиболее производный метакласс — это тот, который является подтипом всех этих кандидатных метаклассов. Если ни один из кандидатных метаклассов не соответствует этому критерию, определение класса завершится ошибкой TypeError.
3.3.3.4. Подготовка пространства имён класса
После того, как был определён соответствующий метакласс, пространство имен класса готовится. Если у метакласса есть атрибут __prepare__, он вызывается как namespace = metaclass.__prepare__(name, bases, **kwds) (где дополнительные ключевые аргументы, если таковые имеются, взяты из определения класса). Метод __prepare__ должен быть реализован как classmethod. Возвращаемое пространство имён методом __prepare__ передаётся в __new__, но при создании конечного объекта класса пространство имён копируется в новое dict.
Если у метакласса нет атрибута __prepare__ , пространство имен класса инициализируется как пустое упорядоченное отображение.
См. также
- PEP 3115 — Метаклассы в Python 3000
-
Введён крючок пространства имён
__prepare__
3.3.3.5. Выполнение тела класса
Тело класса выполняется (приблизительно) как exec(body, globals(), namespace). Ключевое различие с обычным вызовом exec() заключается в том, что лексическое область действия позволяет телу класса (включая любые методы) ссылаться на имена из текущей и внешних областей видимости, когда определение класса происходит внутри функции.
Однако, даже когда определение класса происходит внутри функции, методы, определённые внутри класса, по-прежнему не могут видеть имена, определённые на уровне класса. Переменные класса должны быть доступны через первый параметр методов экземпляра или класса, или через неявную лексически связанную ссылку __class__ , описанную в следующем разделе.
3.3.3.6. Создание объекта класса
После заполнения пространства имён класса путём выполнения тела класса объект класса создаётся путём вызова metaclass(name, bases, namespace, **kwds) (дополнительные ключевые слова, переданные сюда, совпадают с теми, что были переданы __prepare__).
Этот объект класса — тот, к которому будет обращаться форма super() с нулевым аргументом. __class__ — это неявная ссылка на замыкание, созданная компилятором, если какие-либо методы в теле класса ссылаются на __class__ или super. Это позволяет нулевой форме super() правильно определить класс, определяемый на основе лексической области видимости, тогда как класс или экземпляр, который использовался для выполнения текущего вызова, определяется на основе первого аргумента, переданного в метод.
Подробность реализации CPython: В CPython 3.6 и новее ячейка __class__ передаётся метаклассу в виде записи __classcell__ в пространстве имен класса. Если она есть, её необходимо передать в вызов type.__new__ для корректной инициализации класса. Если этого не сделать, в Python 3.8 появится ошибка RuntimeError.
При использовании метакласса по умолчанию type или любого метакласса, который в конечном итоге вызывает type.__new__, после создания объекта класса вызываются следующие дополнительные шаги настройки:
- сначала
type.__new__собирает все дескрипторы в пространстве имён класса, определяющие метод__set_name__(); - во-вторых, все эти методы
__set_name__вызываются с определяемым классом и назначенным именем этого дескриптора; - наконец, вызывается крючок
__init_subclass__()для непосредственного родителя нового класса в его порядке разрешения методов.
После создания объекта класса он передаётся декораторам классов, включённым в определение класса (если таковые имеются), а результирующий объект привязывается в локальном пространстве имён как определённый класс.
Когда новый класс создаётся с помощью type.__new__, объект, предоставленный в качестве параметра пространства имён, копируется в новое упорядоченное отображение, а исходный объект удаляется. Новая копия оборачивается в чтение-только прокси, который становится атрибутом __dict__ объекта класса.
См. также
- PEP 3135 — Новый super
-
Описывает неявную
__class__ссылку на замыкание
3.3.3.7. Использование метаклассов
Возможные применения метаклассов безграничны. Некоторые из рассмотренных идей включают перечисления, ведение журнала, проверку интерфейсов, автоматическую делегацию, автоматическое создание свойств, прокси, фреймворки и автоматическое блокирование/синхронизацию ресурсов.
3.3.4. Настройка проверок экземпляров и подклассов
Следующие методы используются для переопределения стандартного поведения встроенных функций isinstance() и issubclass().
В частности, метакласс abc.ABCMeta реализует эти методы, чтобы разрешить добавление абстрактных базовых классов (ABC) в качестве «виртуальных базовых классов» к любому классу или типу (включая встроенные типы), включая другие ABC.
-
class.__instancecheck__(self, instance) -
Возвращает 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. Эмуляция обобщённых типов
При использовании типовых аннотаций часто бывает полезно параметризовать обобщённый тип с использованием квадратных скобок Python. Например, аннотация list[int] может использоваться для обозначения list, в котором все элементы имеют тип int.
См. также
- PEP 484 - Типовые подсказки
-
Представление фреймворка Python для типовых аннотаций
- Типы обобщённых псевдонимов
-
Документация для объектов, представляющих параметризованные обобщённые классы
-
Generics, user-defined generics andtyping.Generic -
Документация о том, как реализовать обобщённые классы, которые можно параметризовать во время выполнения и понимать статическим проверкам типов.
Класс обычно может быть параметризован только в том случае, если он определяет специальный метод класса __class_getitem__().
-
classmethod object.__class_getitem__(cls, key) -
Возвращает объект, представляющий специализацию обобщённого класса с помощью аргументов типа, найденных в key.
При определении в классе,
__class_getitem__()автоматически является методом класса. Поэтому нет необходимости в его декорировании@classmethodпри его определении.
3.3.5.1. Назначение __class_getitem__
Назначение __class_getitem__() — разрешить параметризацию во время выполнения обобщённых классов стандартной библиотеки, чтобы легче применять типовые подсказки к этим классам.
Для реализации пользовательских обобщённых классов, которые могут быть параметризованы во время выполнения и понятны статическими проверкам типов, пользователи должны либо наследовать от класса стандартной библиотеки, который уже реализует __class_getitem__(), либо наследовать от typing.Generic, у которого есть собственная реализация __class_getitem__().
Пользовательские реализации __class_getitem__() для классов, определённых вне стандартной библиотеки, могут не пониматься сторонними проверками типов, такими как mypy. Использование __class_getitem__() для любых целей, кроме типовых подсказок, в любом классе не рекомендуется.
3.3.5.2. __class_getitem__ против __getitem__
Обычно, подписка объекта с помощью квадратных скобок вызовет метод экземпляра __getitem__(), определённый в классе объекта. Однако, если подписываемый объект сам является классом, может быть вызван метод класса __class_getitem__(). __class_getitem__() должен вернуть объект GenericAlias, если он должным образом определён.
При столкновении с выражением obj[x], интерпретатор Python выполняет примерно следующий процесс, чтобы решить, следует ли вызвать __getitem__() или __class_getitem__():
from inspect import isclass
def subscribe(obj, x):
"""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 все классы сами по себе являются экземплярами других классов. Класс класса называется метаклассом этого класса, и у большинства классов метаклассом является класс 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 - Основная поддержка модуля typing и обобщённых типов
-
Введение
__class_getitem__()и описание случаев, когда подписка приводит к вызову__class_getitem__()вместо__getitem__()
3.3.6. Эмуляция вызываемых объектов
-
object.__call__(self[, args...]) -
Вызывается при вызове экземпляра как функции; если этот метод определён,
x(arg1, arg2, ...)примерно эквивалентноtype(x).__call__(x, arg1, ...).
3.3.7. Эмуляция типов контейнеров
Следующие методы могут быть определены для реализации контейнерных объектов. Контейнеры обычно являются последовательностями (такими как lists или tuples) или отображениями (например, dictionaries), но также могут представлять и другие контейнеры. Первый набор методов используется для эмуляции последовательности или отображения; разница заключается в том, что для последовательности допустимыми ключами должны быть целые числа k, для которых 0 <= k <
N , где N — длина последовательности, или объекты slice, которые определяют диапазон элементов. Также рекомендуется, чтобы отображения предоставляли методы keys(), values(), items(), get(), clear(), setdefault(), pop(), popitem(), copy(), и update(), работающие аналогично методам стандартных объектов Python dictionary. Модуль collections.abc предоставляет MutableMapping абстрактный базовый класс для создания этих методов на основе базового набора методов __getitem__(), __setitem__(), __delitem__() и keys(). Изменяемые последовательности должны предоставлять методы append(), count(), index(), extend(), insert(), pop(), remove(), reverse() и sort(), как в стандартных объектах Python list. Наконец, типы последовательностей должны реализовывать сложение (то есть конкатенацию) и умножение (то есть повторение), определив методы __add__(), __radd__(), __iadd__(), __mul__(), __rmul__() и __imul__(), описанные ниже; они не должны определять другие числовые операторы. Рекомендуется, чтобы и отображения, и последовательности реализовывали метод __contains__() для эффективного использования оператора in; для отображений in должен искать ключи отображения; для последовательностей он должен искать значения.
Также рекомендуется, чтобы и отображения, и последовательности реализовывали метод __iter__() для эффективной итерации по контейнеру; для отображений __iter__() должен итерироваться по ключам объекта; для последовательностей — по значениям.
-
object.__len__(self) -
Вызывается для реализации встроенной функции
len(). Должен возвращать длину объекта, целое число>=0. Также объект, не определяющий метод__bool__()и чей метод__len__()возвращает ноль, считается ложным в контексте булевых значений.Деталь реализации CPython: в CPython длина должна быть не более
sys.maxsize. Если длина большеsys.maxsize, некоторые функции (например,len()) могут вызватьOverflowError. Чтобы предотвратить исключениеOverflowErrorпри проверке истинности, объект должен определить метод__bool__().
-
object.__length_hint__(self) -
Вызывается для реализации
operator.length_hint(). Должен возвращать приблизительную длину объекта (которая может быть больше или меньше фактической длины). Длина должна быть целым числом>=0. Возвращаемое значение также может бытьNotImplemented, что обрабатывается так же, как если бы метод__length_hint__вообще не существовал. Этот метод — чисто оптимизационный и никогда не требуется для корректности.Добавлена в версии 3.4.
Примечание
Срезы выполняются исключительно с помощью следующих трех методов. Вызов, подобный
a[1:2] = b
преобразуется в
a[slice(1, 2, None)] = b
и так далее. Пропущенные элементы среза всегда заполняются None.
-
object.__getitem__(self, key) -
Вызывается для реализации оценки
self[key]. Для типов последовательностей допустимыми ключами должны быть целые числа и объекты срезов. Обратите внимание, что специальная интерпретация отрицательных индексов (если класс хочет эмулировать тип последовательности) зависит от метода__getitem__(). Если тип key неподходящий, может быть поднято исключениеTypeError; если значение за пределами набора индексов для последовательности (после любой специальной интерпретации отрицательных значений), должно быть поднято исключениеIndexError. Для типов отображений, если key отсутствует (не содержится в контейнере), должно быть поднято исключениеKeyError.Примечание
Циклы
forожидают, что исключениеIndexErrorбудет поднято для недопустимых индексов, чтобы обеспечить правильное обнаружение конца последовательности.Примечание
При подстановке в класс может вызываться специальный метод класса
__class_getitem__()вместо__getitem__(). Подробнее см. __class_getitem__ против __getitem__.
-
object.__setitem__(self, key, value) -
Вызывается для реализации присваивания
self[key]. То же примечание, что и для__getitem__(). Этот метод должен быть реализован только для отображений, если объекты поддерживают изменения значений для ключей или добавление новых ключей, или для последовательностей, если элементы могут быть заменены. Те же исключения должны быть подняты для недопустимых значений key, что и для метода__getitem__().
-
object.__delitem__(self, key) -
Вызывается для реализации удаления
self[key]. То же примечание, что и для__getitem__(). Этот метод должен быть реализован только для отображений, если объекты поддерживают удаление ключей, или для последовательностей, если элементы можно удалить из последовательности. Те же исключения должны быть подняты для недопустимых значений key, что и для метода__getitem__().
-
object.__missing__(self, key) -
Вызывается объектом
dict.__getitem__()для реализацииself[key]для подклассов dict, когда ключ не находится в словаре.
-
object.__iter__(self) -
Этот метод вызывается, когда для контейнера требуется итератор. Этот метод должен вернуть новый объект итератора, который может перебирать все объекты в контейнере. Для отображений он должен перебирать ключи контейнера.
Объекты-итераторы также должны реализовывать этот метод; они должны возвращать себя. Дополнительную информацию об объектах-итераторах см. в Типах итераторов.
-
object.__reversed__(self) -
Вызывается (если присутствует) встроенной функцией
reversed()для реализации обратной итерации. Он должен вернуть новый объект итератора, который перебирает все объекты в контейнере в обратном порядке.Если метод
__reversed__()не предоставлен, встроенная функцияreversed()будет использовать протокол последовательности (__len__()и__getitem__()). Объекты, поддерживающие протокол последовательности, должны предоставлять__reversed__()только если они могут предоставить реализацию, более эффективную, чем реализация, предоставленная функциейreversed().
Операторы проверки на вхождение (in и not in) обычно реализуются как итерация по контейнеру. Однако объекты контейнеров могут предоставить следующий специальный метод с более эффективной реализацией, которая также не требует, чтобы объект был итерируемым.
-
object.__contains__(self, item) -
Вызывается для реализации операторов проверки на вхождение. Должен возвращать true, если item находится в self, и false в противном случае. Для объектов-отображений это должно учитывать ключи отображения, а не значения или пары ключ-значение.
Для объектов, которые не определяют
__contains__(), проверка на вхождение сначала пытается выполнить итерацию через__iter__(), а затем использует старый протокол итерации последовательностей через__getitem__(), см. данный раздел в справочнике языка.
3.3.8. Эмуляция числовых типов
Следующие методы могут быть определены для эмуляции числовых объектов. Методы, соответствующие операциям, которые не поддерживаются конкретным типом числа (например, побитовые операции для нецелых чисел), должны быть оставлены неопределенными.
-
object.__add__(self, other) -
object.__sub__(self, other) -
object.__mul__(self, other) -
object.__matmul__(self, other) -
object.__truediv__(self, other) -
object.__floordiv__(self, other) -
object.__mod__(self, other) -
object.__divmod__(self, other) -
object.__pow__(self, other[, modulo]) -
object.__lshift__(self, other) -
object.__rshift__(self, other) -
object.__and__(self, other) -
object.__xor__(self, other) -
object.__or__(self, other) -
Эти методы вызываются для реализации бинарных арифметических операций (
+,-,*,@,/,//,%,divmod(),pow(),**,<<,>>,&,^,|). Например, для вычисления выраженияx + y, где x — экземпляр класса с методом__add__(), вызываетсяx.__add__(y). Метод__divmod__()должен быть эквивалентен использованию__floordiv__()и__mod__(); он не должен быть связан с__truediv__(). Обратите внимание, что__pow__()должен быть определён для принятия необязательного третьего аргумента, если необходимо поддерживать троичную версию встроенной функцииpow().Если один из этих методов не поддерживает операцию с предоставленными аргументами, он должен вернуть
NotImplemented.
-
object.__radd__(self, other) -
object.__rsub__(self, other) -
object.__rmul__(self, other) -
object.__rmatmul__(self, other) -
object.__rtruediv__(self, other) -
object.__rfloordiv__(self, other) -
object.__rmod__(self, other) -
object.__rdivmod__(self, other) -
object.__rpow__(self, other[, modulo]) -
object.__rlshift__(self, other) -
object.__rrshift__(self, other) -
object.__rand__(self, other) -
object.__rxor__(self, other) -
object.__ror__(self, other) -
Эти методы вызываются для реализации бинарных арифметических операций (
+,-,*,@,/,//,%,divmod(),pow(),**,<<,>>,&,^,|), где операнды отражены (поменяны местами). Эти функции вызываются только в том случае, если левый операнд не поддерживает соответствующую операцию 3 и операнды разных типов. 4 Например, чтобы вычислить выражениеx - y, где y — экземпляр класса с методом__rsub__(), вызываетсяy.__rsub__(x)еслиx.__sub__(y)возвращает NotImplemented.Обратите внимание, что троичная функция
pow()не будет пытаться вызвать__rpow__()(правила приведения типов станут слишком сложными).Примечание
Если тип правого операнда является подклассом типа левого операнда, и этот подкласс предоставляет другое реализацию отражённого метода для операции, этот метод будет вызван перед неотражённым методом левого операнда. Это поведение позволяет подклассам переопределять операции своих предков.
-
object.__iadd__(self, other) -
object.__isub__(self, other) -
object.__imul__(self, other) -
object.__imatmul__(self, other) -
object.__itruediv__(self, other) -
object.__ifloordiv__(self, other) -
object.__imod__(self, other) -
object.__ipow__(self, other[, modulo]) -
object.__ilshift__(self, other) -
object.__irshift__(self, other) -
object.__iand__(self, other) -
object.__ixor__(self, other) -
object.__ior__(self, other) -
Эти методы вызываются для реализации расширенных арифметических присваиваний (
+=,-=,*=,@=,/=,//=,%=,**=,<<=,>>=,&=,^=,|=). Эти методы должны попытаться выполнить операцию на месте (изменить self) и вернуть результат (который может, но не обязательно, быть self). Если определённый метод не определён, расширенное присваивание возвращается к обычным методам. Например, если x — экземпляр класса с методом__iadd__(),x += yэквивалентноx = x.__iadd__(y). В противном случае, рассматриваютсяx.__add__(y)иy.__radd__(x), как и при вычисленииx + y. В определённых ситуациях расширенное присваивание может привести к непредвиденным ошибкам (см. Почему a_tuple[i] += [‘item’] вызывает исключение, когда сложение работает?), но это поведение на самом деле является частью модели данных.Примечание
Из-за ошибки в механизме диспетчеризации для
**=, класс, который определяет__ipow__(), но возвращаетNotImplemented, не сможет перейти кx.__pow__(y)иy.__rpow__(x). Эта ошибка исправлена в Python 3.10.
-
object.__neg__(self) -
object.__pos__(self) -
object.__abs__(self) -
object.__invert__(self) -
Вызывается для реализации унарных арифметических операций (
-,+,abs()и~).
-
object.__complex__(self) -
object.__int__(self) -
object.__float__(self) -
Вызывается для реализации встроенных функций
complex(),int()иfloat(). Должен вернуть значение соответствующего типа.
-
object.__index__(self) -
Вызывается для реализации
operator.index(), и всякий раз, когда Python нужно безнадежно преобразовать числовой объект в целочисленный объект (например, при нарезке или в встроенных функцияхbin(),hex()иoct()). Наличие этого метода указывает на то, что числовой объект является целочисленным типом. Должен вернуть целое число.Если
__int__(),__float__()и__complex__()не определены, соответствующие встроенные функцииint(),float()иcomplex()обращаются к__index__().
-
object.__round__(self[, ndigits]) -
object.__trunc__(self) -
object.__floor__(self) -
object.__ceil__(self) -
Вызывается для реализации встроенной функции
round()и функцийmathtrunc(),floor()иceil(). Если параметр ndigits не передан в__round__(), все эти методы должны возвращать значение объекта, усечённого доIntegral(обычноint).Встроенная функция
int()обращается к__trunc__(), если ни__int__(), ни__index__()не определены.
3.3.9. Управляющие контексты оператора with
Управляющий контекст — это объект, который определяет среду выполнения, которая должна быть установлена при выполнении оператора with. Управляющий контекст обрабатывает вход в желаемую среду выполнения и выход из неё для выполнения блока кода. Управляющие контексты обычно вызываются с помощью оператора with (описанного в разделе Оператор with), но также могут быть вызваны путём непосредственного вызова их методов.
Типичные примеры использования управляющих контекстов включают сохранение и восстановление различных типов глобального состояния, блокировку и разблокировку ресурсов, закрытие открытых файлов и т. д.
Дополнительную информацию о управляющих контекстах см. в Типы управляющих контекстов.
-
object.__enter__(self) -
Вход в среду выполнения, связанную с этим объектом. Оператор
withсвяжет возвращаемое значение этого метода с целевым(и) объектом(ами), указанным(и) в частиasоператора, если таковые имеются.
-
object.__exit__(self, exc_type, exc_value, traceback) -
Выход из среды выполнения, связанной с этим объектом. Параметры описывают исключение, которое вызвало выход из контекста. Если контекст покинут без исключения, все три аргумента будут
None.Если передано исключение и метод хочет его подавить (то есть предотвратить распространение), он должен вернуть значение истины. В противном случае исключение будет обработано обычным образом при выходе из этого метода.
Обратите внимание, что методы
__exit__()не должны повторно генерировать переданное исключение; это ответственность вызывающего кода.
3.3.10. Поиск специальных методов
Для пользовательских классов неявные вызовы специальных методов гарантируют правильную работу только в том случае, если они определены в типе объекта, а не в словаре экземпляра. Вот почему следующий код вызывает исключение:
>>> class C: ... pass ... >>> c = C() >>> c.__len__ = lambda: 5 >>> len(c) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: object of type 'C' has no len()
Основанием для такого поведения является ряд специальных методов, таких как __hash__() и __repr__(), которые реализуются всеми объектами, включая объекты типа. Если неявный поиск этих методов использовал обычный процесс поиска, они потерпели бы неудачу при вызове на объекте типа:
>>> 1 .__hash__() == hash(1) True >>> int.__hash__() == hash(int) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: descriptor '__hash__' of 'int' object needs an argument
Попытка неправильно вызвать несвязанный метод класса таким образом иногда называется «путаницей метаклассов» и избегается путём обхода экземпляра при поиске специальных методов:
>>> type(1).__hash__(1) == hash(1) True >>> type(int).__hash__(int) == hash(int) True
Помимо обхода атрибутов экземпляра для обеспечения корректности, неявный поиск специальных методов, как правило, также обходит метод __getattribute__(), даже метакласса объекта:
>>> class Meta(type):
... def __getattribute__(*args):
... print("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__(). Объекты корутин, возвращаемые функциями с async def, являются объектами-ожиданиями.
Примечание
Объекты-итераторы генераторов, возвращаемые из генераторов, декорированных types.coroutine() или asyncio.coroutine(), также являются объектами-ожиданиями, но они не реализуют метод __await__().
-
object.__await__(self) -
Должен возвращать итератор. Используется для реализации объектов-ожидания. Например,
asyncio.Futureреализует этот метод для совместимости с выражениемawait.
Введено в версии 3.5.
См. также
PEP 492 для дополнительной информации об объектах-ожиданиях.
3.4.2. Объекты корутин
Объекты корутин являются объектами-ожиданиями. Выполнение корутины можно контролировать, вызывая __await__() и итерируясь по результату. Когда корутина завершает выполнение и возвращает значение, итератор генерирует исключение StopIteration, а атрибут value исключения содержит возвращаемое значение. Если корутина генерирует исключение, оно передаётся итератором. Корутины не должны напрямую генерировать необработанные исключения StopIteration.
Корутины также имеют перечисленные ниже методы, аналогичные методам генераторов (см. Методы итераторов генераторов). Однако, в отличие от генераторов, корутины напрямую не поддерживают итерацию.
Изменено в версии 3.5.2: Вызов корутины более одного раза приведёт к исключению RuntimeError.
-
coroutine.send(value) -
Запускает или возобновляет выполнение корутины. Если value равно
None, это эквивалентно продвижению итератора, возвращённого методом__await__(). Если value не равноNone, этот метод делегирует методsend()итератора, который приостановил корутину. Результат (возвращаемое значение,StopIterationили другое исключение) совпадает с результатом при итерировании по значению, возвращённому__await__(), описанному выше.
-
coroutine.throw(value) -
coroutine.throw(type[, value[, traceback]]) -
Генерирует указанное исключение в корутине. Этот метод делегирует метод
throw()итератора, приостановившего корутину, если такой метод существует. В противном случае, исключение генерируется в точке приостановки. Результат (возвращаемое значение,StopIterationили другое исключение) совпадает с результатом при итерировании по значению, возвращённому__await__(), описанному выше. Если исключение не обрабатывается в корутине, оно передаётся обратно вызывающей стороне.
-
coroutine.close() -
Заставляет корутину очиститься и выйти. Если корутина приостановлена, этот метод сначала делегирует метод
close()итератора, который приостановил корутину, если такой метод существует. Затем он генерируетGeneratorExitв точке приостановки, заставляя корутину немедленно очиститься. В конечном счёте корутина помечается как завершённая, даже если она не запускалась.Объекты корутин автоматически закрываются с помощью вышеописанного процесса при уничтожении.
3.4.3. Асинхронные итераторы
Асинхронный итератор может вызывать асинхронный код в своём методе __anext__.
Асинхронные итераторы могут использоваться в инструкции async for.
-
object.__aiter__(self) -
Должен возвращать объект асинхронного итератора.
-
object.__anext__(self) -
Должен возвращать объект-ожидание, приводящий к следующему значению итератора. Должно генерировать ошибку
StopAsyncIteration, когда итерация завершена.
Пример асинхронного итерируемого объекта:
class Reader:
async def readline(self):
...
def __aiter__(self):
return self
async def __anext__(self):
val = await self.readline()
if val == b'':
raise StopAsyncIteration
return val
Введено в версии 3.5.
Изменено в версии 3.7: До Python 3.7, __aiter__() мог возвращать объект-ожидание, который бы разрешился в асинхронный итератор.
Начиная с Python 3.7, __aiter__() должен возвращать объект асинхронного итератора. Возврат чего-либо другого приведёт к ошибке TypeError.
3.4.4. Асинхронные контекстные менеджеры
Асинхронный контекстный менеджер — это контекстный менеджер, который может приостановить выполнение в своих методах __aenter__ и __aexit__.
Асинхронные контекстные менеджеры могут использоваться в операторе async with.
-
object.__aenter__(self) -
Семантически подобен
__enter__(), единственное отличие состоит в том, что он должен возвращать awaitable.
-
object.__aexit__(self, exc_type, exc_value, traceback) -
Семантически подобен
__exit__(), единственное отличие состоит в том, что он должен возвращать awaitable.
Пример класса асинхронного контекстного менеджера:
class AsyncContextManager:
async def __aenter__(self):
await log('entering context')
async def __aexit__(self, exc_type, exc, tb):
await log('exiting context')
Введено в версии 3.5.
Примечания
-
1 -
В некоторых случаях возможно изменить тип объекта при определённых контролируемых условиях. Однако, обычно это не рекомендуется, так как это может привести к очень странному поведению при неправильной обработке.
-
2 -
Методы
__hash__(),__iter__(),__reversed__()и__contains__()имеют особую обработку в этом случае; другие методы по-прежнему будут подниматьTypeError, но могут делать это, полагаясь на поведение, когдаNoneне является вызываемым. -
3 -
«Не поддерживает» в данном случае означает, что у класса нет такого метода или метод возвращает
NotImplemented. Не устанавливайте метод вNone, если вы хотите принудительно использовать отражённый метод правого операнда — это вместо этого будет иметь противоположный эффект, явно блокируя такой возврат. -
4 -
Для операндов одного типа предполагается, что если неотражённый метод — такой как
__add__()— не удаётся, то операция в целом не поддерживается, поэтому отражённый метод не вызывается.
© 2001–2022 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.9/reference/datamodel.html