3. Модель данных¶
3.1. Объекты, значения и типы¶
Objects - это абстракция Python для данных. Все данные в программе Python представлены объектами или отношениями между объектами. (В некотором смысле, в соответствии с моделью фон Неймана о «компьютере с хранимой программой», код также представлен объектами).
Каждый объект имеет идентификатор, тип и значение. Идентичность объекта никогда не меняется после его создания; можно считать, что это адрес объекта в памяти. Оператор „is
“ сравнивает идентичность двух объектов; функция id()
возвращает целое число, представляющее его идентичность.
CPython implementation detail: Для CPython, id(x)
- это адрес памяти, где хранится x
.
Тип объекта определяет операции, которые поддерживает объект (например, «имеет ли он длину?»), а также определяет возможные значения для объектов этого типа. Функция type()
возвращает тип объекта (который сам является объектом). Как и идентификатор, type объекта также неизменен. 1
Значение* некоторых объектов может меняться. Объекты, значение которых может изменяться, называются изменяемыми; объекты, значение которых неизменно после их создания, называются изменяемыми. (Значение неизменяемого объекта-контейнера, содержащего ссылку на изменяемый объект, может измениться при изменении значения последнего; однако контейнер по-прежнему считается неизменяемым, поскольку коллекция объектов, которую он содержит, не может быть изменена. Таким образом, неизменяемость - это не совсем то же самое, что неизменное значение, это более тонкая вещь). Возможность изменения объекта определяется его типом; например, числа, строки и кортежи являются неизменяемыми, а словари и списки - изменяемыми.
Объекты никогда не уничтожаются явно; однако, когда они становятся недоступными, они могут быть собраны в мусор. Реализация может отложить сборку мусора или вообще ее пропустить - это вопрос качества реализации, как будет реализована сборка мусора, до тех пор, пока не будут собраны объекты, которые все еще доступны.
CPython implementation detail: В настоящее время 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
. Он используется для обозначения отсутствия значения во многих ситуациях, например, возвращается из функций, которые явно ничего не возвращают. Его истинностное значение равно false.- NotImplemented
Этот тип имеет единственное значение. Существует единственный объект с этим значением. Доступ к этому объекту осуществляется через встроенное имя
NotImplemented
. Числовые методы и методы сравнения должны возвращать это значение, если они не реализуют операцию для предоставленных операндов. (Интерпретатор будет пытаться использовать отраженную операцию или какой-либо другой запасной вариант, в зависимости от оператора). Это значение не должно оцениваться в булевом контексте.Более подробную информацию см. в разделе Реализация арифметических операций.
Изменено в версии 3.9: Вычисление
NotImplemented
в булевом контексте устарело. Хотя в настоящее время она оценивается как true, она будет выдаватьDeprecationWarning
. В будущих версиях Python он будет вызыватьTypeError
.- Эллипсис
Этот тип имеет единственное значение. Существует единственный объект с этим значением. Доступ к этому объекту осуществляется через литерал
...
или встроенное имяEllipsis
. Его истинностное значение - true.numbers.Number
Они создаются числовыми литералами и возвращаются в качестве результатов арифметическими операторами и арифметическими встроенными функциями. Числовые объекты неизменяемы; после создания их значение никогда не меняется. Числа Python, конечно, сильно связаны с математическими числами, но с учетом ограничений числового представления в компьютерах.
Строковые представления числовых классов, вычисляемые по
__repr__()
и__str__()
, обладают следующими свойствами:Они являются допустимыми числовыми литералами, которые при передаче в конструктор своего класса создают объект, имеющий значение исходного числа.
Представление ведется по основанию 10, когда это возможно.
Ведущие нули, возможно, за исключением одного нуля перед десятичной точкой, не отображаются.
Последующие нули, возможно, за исключением одного нуля после десятичной точки, не отображаются.
Знак указывается только в том случае, если число отрицательное.
Python различает целые числа, числа с плавающей запятой и комплексные числа:
numbers.Integral
Они представляют собой элементы из математического набора целых чисел (положительных и отрицательных).
Существует два типа целых чисел:
- Целые числа (
int
) Они представляют числа в неограниченном диапазоне, в зависимости только от доступной (виртуальной) памяти. Для операций сдвига и маски предполагается двоичное представление, а отрицательные числа представляются в варианте дополнения 2, что создает иллюзию бесконечной строки знаковых битов, простирающейся влево.
- Булевы (
bool
) Они представляют истинностные значения False и True. Два объекта, представляющие значения
False
иTrue
, являются единственными булевыми объектами. Тип Boolean является подтипом типа integer, и значения Boolean ведут себя как значения 0 и 1, соответственно, почти во всех контекстах, за исключением того, что при преобразовании в строку возвращаются строки"False"
или"True"
, соответственно.
Правила представления целых чисел предназначены для наиболее осмысленной интерпретации операций сдвига и маскирования с отрицательными целыми числами.
- Целые числа (
numbers.Real
(float
)Они представляют собой машинные числа двойной точности с плавающей точкой. Вы находитесь во власти базовой архитектуры машины (и реализации C или Java) в отношении допустимого диапазона и обработки переполнения. Python не поддерживает числа с плавающей запятой одинарной точности; экономия в использовании процессора и памяти, которая обычно является причиной их использования, затмевает накладные расходы на использование объектов в Python, поэтому нет причин усложнять язык двумя видами чисел с плавающей запятой.
numbers.Complex
(complex
)Они представляют комплексные числа в виде пары машинных чисел двойной точности с плавающей точкой. Здесь действуют те же предостережения, что и для чисел с плавающей запятой. Действительную и мнимую части комплексного числа
z
можно получить через атрибутыz.real
иz.imag
, доступные только для чтения.
- Последовательности
Они представляют собой конечные упорядоченные множества, индексируемые неотрицательными числами. Встроенная функция
len()
возвращает количество элементов последовательности. Когда длина последовательности равна n, индексный набор содержит числа 0, 1, …, n-1. Элемент i последовательности a выбирается функциейa[i]
.Последовательности также поддерживают нарезку:
a[i:j]
выбирает все элементы с индексом k такие, что i<=
k<
j. При использовании в качестве выражения, срез - это последовательность одного типа. Это означает, что набор индексов перенумерован так, что начинается с 0.Некоторые последовательности также поддерживают «расширенную нарезку» с третьим параметром «шаг»:
a[i:j:k]
выбирает все элементы a с индексом x, гдеx = i + n*k
, n>=
0
и i<=
x<
j.Последовательности различаются в зависимости от их изменяемости:
- Неизменяемые последовательности
Объект неизменяемого типа последовательности не может измениться после его создания. (Если объект содержит ссылки на другие объекты, эти другие объекты могут быть изменяемыми и могут быть изменены; однако коллекция объектов, на которые непосредственно ссылается неизменяемый объект, не может измениться).
Следующие типы являются неизменяемыми последовательностями:
- Струны
Строка - это последовательность значений, представляющих кодовые точки Unicode. Все кодовые точки в диапазоне
U+0000 - U+10FFFF
могут быть представлены в строке. В Python нет типа char; вместо этого каждая кодовая точка в строке представляется как строковый объект длиной1
. Встроенная функцияord()
преобразует кодовую точку из строковой формы в целое число в диапазоне0 - 10FFFF
;chr()
преобразует целое число в диапазоне0 - 10FFFF
в соответствующий строковый объект длины1
.str.encode()
может использоваться для преобразованияstr
вbytes
с использованием заданной текстовой кодировки, аbytes.decode()
может использоваться для достижения обратного результата.- Кортежи
Элементы кортежа - это произвольные объекты Python. Кортежи из двух или более элементов формируются из списков выражений, разделенных запятыми. Кортеж из одного элемента («синглтон») может быть сформирован путем присоединения запятой к выражению (выражение само по себе не создает кортеж, поскольку круглые скобки должны использоваться для группировки выражений). Пустой кортеж может быть образован пустой парой круглых скобок.
- Байты
Объект bytes - это неизменяемый массив. Элементами являются 8-битные байты, представленные целыми числами в диапазоне 0 <= x < 256. Для создания байтовых объектов можно использовать литералы байтов (например,
b'abc'
) и встроенный конструкторbytes()
. Также объекты байтов могут быть декодированы в строки с помощью методаdecode()
.
- Мутируемые последовательности
Мутабельные последовательности могут быть изменены после их создания. Нотации подписки и нарезки могут использоваться в качестве цели операторов присваивания и
del
(удаления).В настоящее время существует два внутренних изменяемых типа последовательностей:
- Списки
Элементы списка - это произвольные объекты Python. Списки формируются путем помещения списка выражений, разделенных запятыми, в квадратные скобки. (Обратите внимание, что для формирования списков длины 0 или 1 не требуется никаких специальных случаев).
- Массивы байтов
Объект bytearray - это изменяемый массив. Они создаются встроенным конструктором
bytearray()
. Помимо того, что байтовые массивы являются изменяемыми (и, следовательно, нехешируемыми), в остальном они предоставляют тот же интерфейс и функциональность, что и неизменяемые объектыbytes
.
Модуль расширения
array
предоставляет дополнительный пример изменяемого типа последовательности, как и модульcollections
.
- Типы комплектов
Они представляют собой неупорядоченные, конечные наборы уникальных, неизменяемых объектов. Как таковые, они не могут быть проиндексированы каким-либо подмножеством. Однако их можно итерировать, а встроенная функция
len()
возвращает количество элементов в наборе. Обычно множества используются для быстрого тестирования принадлежности, удаления дубликатов из последовательности и вычисления математических операций, таких как пересечение, объединение, разность и симметричная разность.Для элементов множества действуют те же правила неизменяемости, что и для ключей словаря. Обратите внимание, что числовые типы подчиняются обычным правилам числового сравнения: если два числа сравниваются одинаково (например,
1
и1.0
), только одно из них может содержаться в множестве.В настоящее время существует два типа внутренних наборов:
- Устанавливает
Они представляют собой изменяемое множество. Они создаются встроенным конструктором
set()
и могут быть изменены впоследствии несколькими методами, такими какadd()
.- Замороженные декорации
Они представляют собой неизменяемое множество. Они создаются встроенным конструктором
frozenset()
. Поскольку фростенсет неизменяем и hashable, он может быть использован снова как элемент другого множества или как ключ словаря.
- Отображения
Они представляют собой конечные множества объектов, индексированных произвольными наборами индексов. Подстрочная нотация
a[k]
выбирает элемент, индексированныйk
из отображенияa
; его можно использовать в выражениях и в качестве цели присваиваний или операторовdel
. Встроенная функцияlen()
возвращает количество элементов в отображении.В настоящее время существует единственный тип внутренней привязки:
- Словари
Они представляют собой конечные наборы объектов, индексируемых практически произвольными значениями. Единственные типы значений, неприемлемые в качестве ключей, - это значения, содержащие списки, словари или другие изменяемые типы, которые сравниваются по значению, а не по идентичности объекта; причина в том, что эффективная реализация словарей требует, чтобы хэш-значение ключа оставалось постоянным. Числовые типы, используемые для ключей, подчиняются обычным правилам числового сравнения: если два числа сравниваются одинаково (например,
1
и1.0
), то их можно использовать для индексации одной и той же словарной статьи.Словари сохраняют порядок вставки, что означает, что ключи будут создаваться в том же порядке, в котором они были последовательно добавлены в словарь. Замена существующего ключа не изменит порядок, однако удаление ключа и его повторная вставка добавит его в конец вместо того, чтобы сохранить его прежнее место.
Словари являются изменяемыми; они могут быть созданы с помощью нотации
{...}
(см. раздел Отображения в словаре).Модули расширения
dbm.ndbm
иdbm.gnu
предоставляют дополнительные примеры типов отображения, как и модульcollections
.Изменено в версии 3.7: Словари не сохраняли порядок вставки в версиях Python до 3.6. В CPython 3.6 порядок вставки был сохранен, но в то время это считалось деталью реализации, а не гарантией языка.
- Вызываемые типы
Это типы, к которым может быть применена операция вызова функции (см. раздел Звонки):
- Определяемые пользователем функции
Объект пользовательской функции создается определением функции (см. раздел Определения функций). Он должен вызываться со списком аргументов, содержащим то же количество элементов, что и список формальных параметров функции.
Специальные атрибуты:
Атрибут
Значение
__doc__
Строка документации функции, или
None
, если она недоступна; не наследуется подклассами.Записываемый
Имя функции.
Записываемый
Функция qualified name.
Добавлено в версии 3.3.
Записываемый
__module__
Имя модуля, в котором была определена функция, или
None
, если он недоступен.Записываемый
__defaults__
Кортеж, содержащий значения аргументов по умолчанию для тех аргументов, которые имеют значения по умолчанию, или
None
, если ни один аргумент не имеет значения по умолчанию.Записываемый
__code__
Объект кода, представляющий скомпилированное тело функции.
Записываемый
__globals__
Ссылка на словарь, хранящий глобальные переменные функции — глобальное пространство имен модуля, в котором была определена функция.
Только для чтения
Пространство имен, поддерживающее произвольные атрибуты функций.
Записываемый
__closure__
None
или кортеж ячеек, содержащих привязки для свободных переменных функции. Информацию об атрибутеcell_contents
см. ниже.Только для чтения
__annotations__
Диктант, содержащий аннотации параметров. Ключами dict являются имена параметров, а
'return'
- аннотация return, если она предусмотрена. Для получения дополнительной информации о работе с этим атрибутом смотрите Лучшие методы работы с аннотациями.Записываемый
__kwdefaults__
Диктант, содержащий значения по умолчанию для параметров только для ключевых слов.
Записываемый
Большинство атрибутов, помеченных как «Записываемые», проверяют тип присваиваемого значения.
Объекты функций также поддерживают получение и установку произвольных атрибутов, которые могут быть использованы, например, для прикрепления метаданных к функциям. Для получения и установки таких атрибутов используется обычный атрибут dot-notation. Обратите внимание, что текущая реализация поддерживает атрибуты функций только для функций, определяемых пользователем. Атрибуты функций для встроенных функций могут быть поддержаны в будущем.
Объект ячейки имеет атрибут
cell_contents
. Его можно использовать для получения значения ячейки, а также для установки значения.Дополнительная информация об определении функции может быть получена из ее объекта кода; см. описание внутренних типов ниже. К типу
cell
можно получить доступ в модулеtypes
.- Методы экземпляра
Объект метода экземпляра объединяет класс, экземпляр класса и любой вызываемый объект (обычно определяемую пользователем функцию).
Специальные атрибуты, доступные только для чтения:
__self__
- объект экземпляра класса,__func__
- объект функции;__doc__
- документация метода (такая же, как__func__.__doc__
);__name__
- имя метода (такое же, как__func__.__name__
);__module__
- имя модуля, в котором определен метод, илиNone
, если он недоступен.Методы также поддерживают доступ (но не установку) к произвольным атрибутам функции на базовом объекте функции.
Определяемые пользователем объекты методов могут быть созданы при получении атрибута класса (возможно, через экземпляр этого класса), если этот атрибут является объектом определяемой пользователем функции или объектом метода класса.
Когда объект метода экземпляра создается путем извлечения объекта пользовательской функции из класса через один из его экземпляров, его атрибутом
__self__
является экземпляр, а объект метода считается связанным. Атрибутом__func__
нового метода является исходный объект функции.Когда объект метода экземпляра создается путем извлечения объекта метода класса из класса или экземпляра, его атрибутом
__self__
является сам класс, а его атрибутом__func__
является объект функции, лежащий в основе метода класса.Когда вызывается объект метода экземпляра, вызывается базовая функция (
__func__
), вставляя экземпляр класса (__self__
) перед списком аргументов. Например, когдаC
является классом, содержащим определение функцииf()
, аx
является экземпляромC
, вызовx.f(1)
эквивалентен вызовуC.f(x, 1)
.Когда объект метода экземпляра является производным от объекта метода класса, «экземпляр класса», хранящийся в
__self__
, на самом деле будет самим классом, так что вызовx.f(1)
илиC.f(1)
эквивалентен вызовуf(C,1)
, гдеf
является базовой функцией.Обратите внимание, что преобразование из объекта функции в объект метода экземпляра происходит каждый раз, когда атрибут извлекается из экземпляра. В некоторых случаях полезной оптимизацией является присвоение атрибута локальной переменной и вызов этой локальной переменной. Также обратите внимание, что это преобразование происходит только для функций, определенных пользователем; другие вызываемые объекты (и все невызываемые объекты) извлекаются без преобразования. Также важно отметить, что определяемые пользователем функции, которые являются атрибутами экземпляра класса, не преобразуются в связанные методы; это только происходит, когда функция является атрибутом класса.
- Функции генератора
Функция или метод, использующий оператор
yield
(см. раздел Оператор yield), называется generator function. Такая функция при вызове всегда возвращает объект iterator, который может быть использован для выполнения тела функции: вызов метода итератораiterator.__next__()
заставит функцию выполняться до тех пор, пока она не предоставит значение с помощью оператораyield
. Когда функция выполнит операторreturn
или свалится в конец, возникнет исключениеStopIteration
, а итератор достигнет конца набора возвращаемых значений.- Корутинные функции
Функция или метод, определенный с помощью
async def
, называется coroutine function. Такая функция при вызове возвращает объект coroutine. Она может содержать выраженияawait
, а также утвержденияasync with
иasync for
. См. также раздел Объекты Coroutine.- Функции асинхронного генератора
Функция или метод, определенный с помощью
async def
и использующий операторyield
, называется asynchronous generator function. Такая функция при вызове возвращает объект asynchronous iterator, который может быть использован в оператореasync for
для выполнения тела функции.Вызов метода
aiterator.__anext__
асинхронного итератора вернет awaitable, который при ожидании будет выполняться до тех пор, пока не будет получено значение с помощью выраженияyield
. Когда функция выполнит пустое выражениеreturn
или свалится в конец, возникнет исключениеStopAsyncIteration
, а асинхронный итератор достигнет конца набора выдаваемых значений.- Встроенные функции
Объект встроенной функции - это обертка вокруг функции языка Си. Примерами встроенных функций являются
len()
иmath.sin()
(math
является стандартным встроенным модулем). Количество и тип аргументов определяются функцией Си. Специальные атрибуты только для чтения:__doc__
- строка документации функции, илиNone
, если она недоступна;__name__
- имя функции;__self__
устанавливается вNone
(но см. следующий пункт);__module__
- имя модуля, в котором была определена функция, илиNone
, если она недоступна.- Встроенные методы
На самом деле это другая маскировка встроенной функции, на этот раз содержащая объект, передаваемый в функцию C в качестве неявного дополнительного аргумента. Примером встроенного метода является
alist.append()
, предполагающий, что alist - это объект списка. В этом случае специальный атрибут только для чтения__self__
устанавливается на объект, обозначаемый alist.- Занятия
Классы являются вызываемыми. Обычно эти объекты действуют как фабрики для новых экземпляров самих себя, но возможны вариации для типов классов, которые переопределяют
__new__()
. Аргументы вызова передаются в__new__()
и, в типичном случае, в__init__()
для инициализации нового экземпляра.- Экземпляры классов
Экземпляры произвольных классов можно сделать вызываемыми, определив метод
__call__()
в их классе.
- Модули
Модули являются основной организационной единицей кода Python и создаются с помощью оператора import system, вызываемого либо оператором
import
, либо вызовом функций, таких какimportlib.import_module()
и встроенных__import__()
. Объект модуля имеет пространство имен, реализуемое объектом-словарем (это словарь, на который ссылается атрибут__globals__
функций, определенных в модуле). Ссылки на атрибуты переводятся в поиск в этом словаре, например,m.x
эквивалентноm.__dict__["x"]
. Объект модуля не содержит объект кода, используемый для инициализации модуля (поскольку он не нужен после инициализации).Назначение атрибутов обновляет словарь пространств имен модуля, например,
m.x = 1
эквивалентноm.__dict__["x"] = 1
.Предопределенные (записываемые) атрибуты:
__name__
Имя модуля.
__doc__
Строка документации модуля, или
None
, если она недоступна.__file__
Путь к файлу, из которого был загружен модуль, если он был загружен из файла. Атрибут
__file__
может отсутствовать для некоторых типов модулей, таких как модули C, статически подключаемые к интерпретатору. Для модулей расширения, загружаемых динамически из разделяемой библиотеки, это имя пути к файлу разделяемой библиотеки.__annotations__
Словарь, содержащий variable annotations, собранный во время выполнения тела модуля. О лучших практиках работы с
__annotations__
смотрите Лучшие методы работы с аннотациями.
Специальный атрибут, доступный только для чтения:
__dict__
- пространство имен модуля в виде словарного объекта.CPython implementation detail: Из-за того, как CPython очищает словари модулей, словарь модуля будет очищен, когда модуль выйдет из области видимости, даже если в словаре все еще есть живые ссылки. Чтобы избежать этого, скопируйте словарь или держите модуль рядом, используя его словарь напрямую.
- Пользовательские классы
Пользовательские типы классов обычно создаются определениями классов (см. раздел Определения классов). Класс имеет пространство имен, реализуемое объектом-словарем. Ссылки на атрибуты класса переводятся в поиск в этом словаре, например,
C.x
переводится вC.__dict__["x"]
(хотя существует ряд хуков, позволяющих использовать другие способы поиска атрибутов). Если имя атрибута не найдено там, поиск атрибута продолжается в базовых классах. Этот поиск в базовых классах использует порядок разрешения методов C3, который ведет себя правильно даже при наличии «бриллиантовых» структур наследования, где есть несколько путей наследования, ведущих к общему предку. Дополнительные подробности о C3 MRO, используемом в Python, можно найти в документации, сопровождающей выпуск 2.3 по адресу https://www.python.org/download/releases/2.3/mro/.Когда ссылка на атрибут класса (скажем, для класса
C
) дает объект метода класса, она преобразуется в объект метода экземпляра, атрибутом__self__
которого являетсяC
. Если в результате будет получен объект статического метода, он преобразуется в объект, обернутый объектом статического метода. Смотрите раздел Реализация дескрипторов о другом способе, с помощью которого атрибуты, извлекаемые из класса, могут отличаться от тех, которые фактически содержатся в его__dict__
.Назначения атрибутов класса обновляют словарь класса, но не словарь базового класса.
Объект класса может быть вызван (см. выше) для получения экземпляра класса (см. ниже).
Специальные атрибуты:
__name__
Имя класса.
__module__
Имя модуля, в котором был определен класс.
__dict__
Словарь, содержащий пространство имен класса.
__bases__
Кортеж, содержащий базовые классы в порядке их появления в списке базовых классов.
__doc__
Строка документации класса, или
None
, если она не определена.__annotations__
Словарь, содержащий variable annotations, собранный во время выполнения тела класса. О лучших практиках работы с
__annotations__
см. в разделе Лучшие методы работы с аннотациями.
- Экземпляры классов
Экземпляр класса создается путем вызова объекта класса (см. выше). Экземпляр класса имеет пространство имен, реализованное в виде словаря, который является первым местом поиска ссылок на атрибуты. Если атрибут там не найден, а класс экземпляра имеет атрибут с таким именем, поиск продолжается в атрибутах класса. Если найден атрибут класса, который является объектом функции, определяемой пользователем, он преобразуется в объект метода экземпляра, атрибутом которого
__self__
является сам экземпляр. Объекты статических методов и методов классов также преобразуются; см. выше в разделе «Классы». Смотрите раздел Реализация дескрипторов для другого способа, с помощью которого атрибуты класса, получаемые через его экземпляры, могут отличаться от объектов, фактически хранящихся в__dict__
класса. Если атрибут класса не найден, а класс объекта имеет метод__getattr__()
, то вызывается этот метод, чтобы удовлетворить поиск.Присвоение и удаление атрибутов обновляет словарь экземпляра, но не словарь класса. Если у класса есть метод
__setattr__()
или__delattr__()
, он вызывается вместо прямого обновления словаря экземпляра.Экземпляры классов могут притворяться числами, последовательностями или отображениями, если у них есть методы с определенными специальными именами. См. раздел Специальные имена методов.
Специальные атрибуты:
__dict__
- словарь атрибутов;__class__
- класс экземпляра.- Объекты ввода/вывода (также известные как объекты файлов)
Символ file object представляет открытый файл. Для создания файловых объектов доступны различные сочетания клавиш: встроенная функция
open()
, а такжеos.popen()
,os.fdopen()
и методmakefile()
объектов сокетов (и, возможно, другие функции или методы, предоставляемые модулями расширения).Объекты
sys.stdin
,sys.stdout
иsys.stderr
инициализируются файловыми объектами, соответствующими стандартным потокам ввода, вывода и ошибок интерпретатора; все они открыты в текстовом режиме и поэтому следуют интерфейсу, определенному абстрактным классомio.TextIOBase
.- Внутренние типы
Несколько типов, используемых интерпретатором внутри программы, открыты для пользователя. Их определения могут измениться в будущих версиях интерпретатора, но они упомянуты здесь для полноты картины.
- Кодовые объекты
Объекты кода представляют собой байтово-компилированный исполняемый код Python, или bytecode. Разница между объектом кода и объектом функции заключается в том, что объект функции содержит явную ссылку на глобалы функции (модуль, в котором она была определена), а объект кода не содержит контекста; также значения аргументов по умолчанию хранятся в объекте функции, а не в объекте кода (поскольку они представляют собой значения, вычисляемые во время выполнения). В отличие от объектов функций, объекты кода неизменяемы и не содержат ссылок (прямых или косвенных) на изменяемые объекты.
Специальные атрибуты, доступные только для чтения:
co_name
задает имя функции;co_argcount
- общее количество позиционных аргументов (включая позиционные аргументы и аргументы со значениями по умолчанию);co_posonlyargcount
- количество позиционных аргументов (включая аргументы со значениями по умолчанию);co_kwonlyargcount
- количество аргументов только с ключевыми словами (включая аргументы со значениями по умолчанию);co_nlocals
- количество локальных переменных, используемых функцией (включая аргументы);co_varnames
- кортеж, содержащий имена локальных переменных (начиная с имен аргументов);co_cellvars
- кортеж, содержащий имена локальных переменных, на которые ссылаются вложенные функции;co_freevars
- кортеж, содержащий имена свободных переменных;co_code
- строка, представляющая последовательность инструкций байткода;co_consts
- кортеж, содержащий литералы, используемые байткодом;co_names
- кортеж, содержащий имена, используемые байткодом;co_filename
- имя файла, из которого был скомпилирован код;co_firstlineno
- номер первой строки функции;co_lnotab
- строка, кодирующая отображение смещений байткода на номера строк (подробнее см. исходный код интерпретатора);co_stacksize
- требуемый размер стека;co_flags
- целое число, кодирующее ряд флагов интерпретатора.Для
co_flags
определены следующие биты флагов: бит0x04
устанавливается, если функция использует синтаксис*arguments
для приема произвольного числа позиционных аргументов; бит0x08
устанавливается, если функция использует синтаксис**keywords
для приема произвольных аргументов в виде ключевых слов; бит0x20
устанавливается, если функция является генератором.Объявления будущих функций (
from __future__ import division
) также используют биты вco_flags
, чтобы указать, был ли объект кода скомпилирован с включенной определенной функцией: бит0x2000
устанавливается, если функция была скомпилирована с включенным будущим делением; биты0x10
и0x1000
использовались в ранних версиях Python.Другие биты в
co_flags
зарезервированы для внутреннего использования.Если объект кода представляет функцию, то первым элементом в
co_consts
является строка документации функции, илиNone
, если функция не определена.
- Рамочные объекты
Объекты Frame представляют кадры выполнения. Они могут встречаться в объектах трассировки (см. ниже), а также передаются в зарегистрированные функции трассировки.
Специальные атрибуты, доступные только для чтения:
f_back
- к предыдущему кадру стека (в сторону вызывающей стороны), илиNone
, если это нижний кадр стека;f_code
- объект кода, выполняемый в этом кадре;f_locals
- словарь, используемый для поиска локальных переменных;f_globals
используется для глобальных переменных;f_builtins
используется для встроенных (intrinsic) имен;f_lasti
дает точную инструкцию (это индекс в строке байткода объекта кода).Доступ к
f_code
вызывает auditing eventobject.__getattr__
с аргументамиobj
и"f_code"
.Специальные записываемые атрибуты:
f_trace
, если неNone
, является функцией, вызываемой для различных событий во время выполнения кода (используется отладчиком). Обычно событие вызывается для каждой новой строки исходного кода - это можно отключить, установивf_trace_lines
наFalse
.Реализации могут позволить запрашивать события для каждого опкода, установив
f_trace_opcodes
вTrue
. Обратите внимание, что это может привести к неопределенному поведению интерпретатора, если исключения, вызванные функцией трассировки, перейдут в отслеживаемую функцию.f_lineno
- это номер текущей строки кадра — запись в него из функции трассировки переходит на заданную строку (только для самого нижнего кадра). Отладчик может реализовать команду Jump (она же Set Next Statement) путем записи в f_lineno.Объекты фрейма поддерживают один метод:
-
frame.
clear
()¶ Этот метод очищает все ссылки на локальные переменные, принадлежащие кадру. Также, если фрейм принадлежал генератору, генератор финализируется. Это помогает разорвать циклы ссылок с участием объектов фрейма (например, при перехвате исключения и сохранении его трассировки для последующего использования).
RuntimeError
поднимается, если фрейм в данный момент выполняется.Добавлено в версии 3.4.
-
- Отслеживание объектов
Объекты Traceback представляют собой трассировку стека исключения. Объект traceback неявно создается при возникновении исключения, а также может быть явно создан вызовом
types.TracebackType
.Для неявно созданных трассировок, когда поиск обработчика исключения разворачивает стек выполнения, на каждом разворачиваемом уровне объект трассировки вставляется перед текущей трассировкой. Когда вводится обработчик исключения, трассировка стека становится доступной программе. (См. раздел Оператор try.) Он доступен как третий элемент кортежа, возвращаемого командой
sys.exc_info()
, и как атрибут__traceback__
пойманного исключения.Если программа не содержит подходящего обработчика, трассировка стека записывается (с хорошим форматированием) в стандартный поток ошибок; если интерпретатор интерактивен, она также доступна пользователю в виде
sys.last_traceback
.Для явно созданных трассировок, создатель трассировки должен сам определить, как атрибуты
tb_next
должны быть связаны для формирования полной трассировки стека.Специальные атрибуты, доступные только для чтения:
tb_frame
указывает на кадр выполнения текущего уровня;tb_lineno
указывает номер строки, где произошло исключение;tb_lasti
указывает точную инструкцию. Номер строки и последняя инструкция в трассировочном отступлении могут отличаться от номера строки объекта кадра, если исключение произошло в оператореtry
без соответствующей оговорки except или с оговоркой finally.Доступ к
tb_frame
вызывает auditing eventobject.__getattr__
с аргументамиobj
и"tb_frame"
.Специальный записываемый атрибут:
tb_next
- следующий уровень в трассировке стека (по направлению к кадру, где произошло исключение), илиNone
, если следующего уровня нет.Изменено в версии 3.7: Теперь объекты Traceback могут быть явно инстанцированы из кода Python, а атрибут
tb_next
у существующих экземпляров может быть обновлен.- Нарезка объектов
Объекты Slice используются для представления срезов для методов
__getitem__()
. Они также создаются встроенной функциейslice()
.Специальные атрибуты, доступные только для чтения:
start
- нижняя граница;stop
- верхняя граница;step
- значение шага; каждый из нихNone
, если опущен. Эти атрибуты могут иметь любой тип.Объекты Slice поддерживают один метод:
-
slice.
indices
(self, length)¶ Этот метод принимает единственный целочисленный аргумент length и вычисляет информацию о срезе, который объект slice описал бы, если бы был применен к последовательности элементов length. Он возвращает кортеж из трех целых чисел; соответственно это индексы start и stop и длина step или stride среза. Отсутствующие или выходящие за границы индексы обрабатываются в соответствии с обычными срезами.
-
- Объекты статических методов
Статические объекты методов обеспечивают способ преодоления преобразования объектов функций в объекты методов, описанный выше. Статический объект метода - это обертка вокруг любого другого объекта, обычно определяемого пользователем объекта метода. Когда статический объект метода извлекается из класса или экземпляра класса, возвращаемый объект на самом деле является обернутым объектом, который не подвергается дальнейшему преобразованию. Статические объекты методов также можно вызывать. Объекты статических методов создаются с помощью встроенного конструктора
staticmethod()
.- Объекты методов класса
Объект метода класса, как и объект статического метода, представляет собой обертку вокруг другого объекта, которая изменяет способ получения этого объекта из классов и экземпляров классов. Поведение объектов методов классов при таком извлечении описано выше, в разделе «Определяемые пользователем методы». Объекты методов классов создаются встроенным конструктором
classmethod()
.
3.3. Специальные имена методов¶
Класс может реализовать определенные операции, которые вызываются специальным синтаксисом (например, арифметические операции или подписывание и нарезка), определяя методы со специальными именами. Это подход Python к operator overloading, позволяющий классам определять свое собственное поведение по отношению к операторам языка. Например, если класс определяет метод с именем __getitem__()
, а x
является экземпляром этого класса, то x[i]
примерно эквивалентен type(x).__getitem__(x, i)
. За исключением упомянутых случаев, попытки выполнить операцию вызывают исключение, если соответствующий метод не определен (обычно AttributeError
или TypeError
).
Установка специального метода в None
означает, что соответствующая операция недоступна. Например, если класс устанавливает __iter__()
в None
, класс не является итерируемым, поэтому вызов iter()
на его экземплярах вызовет TypeError
(без возврата к __getitem__()
). 2
При реализации класса, эмулирующего любой встроенный тип, важно, чтобы эмуляция была реализована только в той степени, в которой это имеет смысл для моделируемого объекта. Например, некоторые последовательности могут хорошо работать с извлечением отдельных элементов, но извлечение фрагмента может не иметь смысла. (Одним из примеров этого является интерфейс NodeList
в объектной модели документа W3C).
3.3.1. Базовая настройка¶
-
object.
__new__
(cls[, ...])¶ Вызывается для создания нового экземпляра класса cls.
__new__()
- это статический метод (специально выделенный, поэтому его не нужно объявлять как таковой), который в качестве первого аргумента принимает класс, экземпляр которого был запрошен. Остальные аргументы - это аргументы, передаваемые в выражение конструктора объекта (вызов класса). Возвращаемым значением__new__()
должен быть новый экземпляр объекта (обычно экземпляр cls).Типичные реализации создают новый экземпляр класса, вызывая метод суперкласса
__new__()
с помощьюsuper().__new__(cls[, ...])
с соответствующими аргументами, а затем изменяя вновь созданный экземпляр по мере необходимости перед его возвратом.Если во время конструирования объекта вызывается
__new__()
и возвращается экземпляр cls, то метод нового экземпляра__init__()
будет вызван как__init__(self[, ...])
, где self - новый экземпляр, а остальные аргументы те же, что были переданы конструктору объекта.Если
__new__()
не возвращает экземпляр cls, то метод нового экземпляра__init__()
не будет вызван.__new__()
предназначен в основном для того, чтобы позволить подклассам неизменяемых типов (таких как int, str или tuple) настраивать создание экземпляров. Он также часто переопределяется в пользовательских метаклассах для настройки создания классов.
-
object.
__init__
(self[, ...])¶ Вызывается после создания экземпляра (с помощью
__new__()
), но до его возврата вызывающей стороне. Аргументами являются аргументы, переданные в выражении конструктора класса. Если базовый класс имеет метод__init__()
, то метод__init__()
производного класса, если таковой имеется, должен явно вызывать его, чтобы обеспечить правильную инициализацию части экземпляра базового класса; например:super().__init__([args...])
.Поскольку
__new__()
и__init__()
работают вместе при конструировании объектов (__new__()
для создания и__init__()
для настройки), никакое не``None`` значение не может быть возвращено__init__()
; это приведет к возникновениюTypeError
во время выполнения.
-
object.
__del__
(self)¶ Вызывается, когда экземпляр собирается быть уничтоженным. Этот метод также называется финализатором или (неправильно) деструктором. Если базовый класс имеет метод
__del__()
, то метод__del__()
производного класса, если таковой имеется, должен явно вызвать его, чтобы обеспечить надлежащее удаление части экземпляра базового класса.Возможно (хотя и не рекомендуется!), чтобы метод
__del__()
отложил уничтожение экземпляра, создав новую ссылку на него. Это называется воскрешением объекта. Вызывать ли метод__del__()
второй раз, когда воскрешенный объект будет уничтожен, зависит от реализации; текущая реализация CPython вызывает его только один раз.Не гарантируется, что методы
__del__()
будут вызваны для объектов, которые все еще существуют при выходе из интерпретатора.Примечание
del x
не вызывает напрямуюx.__del__()
- первый уменьшает счетчик ссылок дляx
на единицу, а второй вызывается только тогда, когда счетчик ссылокx
достигает нуля.CPython implementation detail: It is possible for a reference cycle to prevent the reference count of an object from going to zero. In this case, the cycle will be later detected and deleted by the cyclic garbage collector. A common cause of reference cycles is when an exception has been caught in a local variable. The frame’s locals then reference the exception, which references its own traceback, which references the locals of all frames caught in the traceback.
См.также
Документация для модуля
gc
.Предупреждение
Из-за нестабильных условий, при которых вызываются методы
__del__()
, исключения, возникающие во время их выполнения, игнорируются, а вместо них выводится предупреждениеsys.stderr
. В частности:__del__()
может быть вызван во время выполнения произвольного кода, в том числе из любого произвольного потока. Если__del__()
необходимо взять блокировку или вызвать любой другой блокирующий ресурс, он может зайти в тупик, поскольку ресурс может быть уже занят кодом, прерванным для выполнения__del__()
.__del__()
может быть выполнена во время закрытия интерпретатора. Как следствие, глобальные переменные, к которым ему необходимо получить доступ (включая другие модули), могут быть уже удалены или установлены в значениеNone
. Python гарантирует, что глобальные переменные, имя которых начинается с одного подчеркивания, удаляются из своего модуля до удаления других глобальных переменных; если других ссылок на такие глобальные переменные не существует, это может помочь в обеспечении того, что импортированные модули все еще доступны в момент вызова метода__del__()
.
-
object.
__repr__
(self)¶ Вызывается встроенной функцией
repr()
для вычисления «официального» строкового представления объекта. Если это вообще возможно, оно должно выглядеть как допустимое выражение Python, которое можно использовать для воссоздания объекта с тем же значением (при соответствующем окружении). Если это невозможно, должна быть возвращена строка вида<...some useful description...>
. Возвращаемое значение должно быть строковым объектом. Если класс определяет__repr__()
, но не__str__()
, то__repr__()
также используется, когда требуется «неформальное» строковое представление экземпляров этого класса.Обычно это используется для отладки, поэтому важно, чтобы представление было информационно насыщенным и однозначным.
-
object.
__str__
(self)¶ Вызывается
str(object)
и встроенными функциямиformat()
иprint()
для вычисления «неформального» или хорошо печатаемого строкового представления объекта. Возвращаемое значение должно быть объектом string.Этот метод отличается от
object.__repr__()
тем, что нет ожидания, что__str__()
вернет правильное выражение Python: можно использовать более удобное или краткое представление.Реализация по умолчанию, определенная встроенным типом
object
, вызываетobject.__repr__()
.
-
object.
__bytes__
(self)¶ Вызывается bytes для вычисления представления байт-строки объекта. Это должно вернуть объект
bytes
.
-
object.
__format__
(self, format_spec)¶ Вызывается встроенной функцией
format()
и, соответственно, оценкой formatted string literals и методомstr.format()
для создания «форматированного» строкового представления объекта. Аргумент format_spec представляет собой строку, содержащую описание желаемых параметров форматирования. Интерпретация аргумента format_spec зависит от типа, реализующего__format__()
, однако большинство классов либо делегируют форматирование одному из встроенных типов, либо используют аналогичный синтаксис опций форматирования.Описание стандартного синтаксиса форматирования см. в разделе Мини-язык спецификации формата.
Возвращаемое значение должно быть строковым объектом.
Изменено в версии 3.4: Метод __format__ метода
object
сам по себе вызывает ошибкуTypeError
, если ему передается любая непустая строка.Изменено в версии 3.7:
object.__format__(x, '')
теперь эквивалентноstr(x)
, а неformat(str(x), '')
.
-
object.
__lt__
(self, other)¶ -
object.
__le__
(self, other)¶ -
object.
__eq__
(self, other)¶ -
object.
__ne__
(self, other)¶ -
object.
__gt__
(self, other)¶ -
object.
__ge__
(self, other)¶ Это так называемые методы «богатого сравнения». Соответствие между символами операторов и именами методов следующее:
x<y
вызываетx.__lt__(y)
,x<=y
вызываетx.__le__(y)
,x==y
вызываетx.__eq__(y)
,x!=y
вызываетx.__ne__(y)
,x>y
вызываетx.__gt__(y)
, иx>=y
вызываетx.__ge__(y)
.Метод богатого сравнения может возвращать синглтон
NotImplemented
, если он не реализует операцию для данной пары аргументов. По соглашению,False
иTrue
возвращаются при успешном сравнении. Однако эти методы могут возвращать любое значение, поэтому если оператор сравнения используется в булевом контексте (например, в условии оператораif
), Python вызоветbool()
на значении, чтобы определить, является ли результат истинным или ложным.По умолчанию
object
реализует__eq__()
с помощьюis
, возвращаяNotImplemented
в случае ложного сравнения:True if x is y else NotImplemented
. Для__ne__()
по умолчанию делегируется__eq__()
и инвертирует результат, если он неNotImplemented
. Других подразумеваемых отношений между операторами сравнения или реализациями по умолчанию не существует; например, истинность(x<y or x==y)
не подразумеваетx<=y
. Чтобы автоматически генерировать операции упорядочивания из одной корневой операции, смотритеfunctools.total_ordering()
.См. параграф о
__hash__()
для некоторых важных замечаний по созданию объектов hashable, которые поддерживают пользовательские операции сравнения и могут использоваться в качестве ключей словаря.Не существует версий этих методов с заменой аргументов (используемых, когда левый аргумент не поддерживает операцию, а правый поддерживает); скорее,
__lt__()
и__gt__()
являются отражением друг друга,__le__()
и__ge__()
являются отражением друг друга, а__eq__()
и__ne__()
являются собственным отражением. Если операнды разных типов, и тип правого операнда является прямым или косвенным подклассом типа левого операнда, то приоритет имеет отраженный метод правого операнда, иначе приоритет имеет метод левого операнда. Виртуальный подкласс не рассматривается.
-
object.
__hash__
(self)¶ Вызывается встроенной функцией
hash()
и для операций над членами хешированных коллекций, включаяset
,frozenset
иdict
. Метод__hash__()
должен возвращать целое число. Единственным требуемым свойством является то, что объекты, которые сравниваются одинаково, имеют одинаковое хэш-значение; рекомендуется смешивать хэш-значения компонентов объекта, которые также играют роль в сравнении объектов, упаковывая их в кортеж и хэшируя кортеж. Пример:def __hash__(self): return hash((self.name, self.nick, self.color))
Примечание
hash()
усекает значение, возвращаемое из пользовательского метода объекта__hash__()
до размераPy_ssize_t
. Обычно это 8 байт в 64-битных сборках и 4 байта в 32-битных сборках. Если__hash__()
объекта должен взаимодействовать на сборках с разным размером бит, обязательно проверьте ширину на всех поддерживаемых сборках. Простой способ сделать это - использоватьpython -c "import sys; print(sys.hash_info.width)"
.Если класс не определяет метод
__eq__()
, он не должен определять и операцию__hash__()
; если он определяет__eq__()
, но не__hash__()
, его экземпляры не могут быть использованы в качестве элементов в хэшируемых коллекциях. Если класс определяет изменяемые объекты и реализует метод__eq__()
, он не должен реализовывать__hash__()
, поскольку реализация хэшируемых коллекций требует, чтобы хэш-значение ключа было неизменным (если хэш-значение объекта изменится, он окажется в неправильном хэш-бакете).Определяемые пользователем классы по умолчанию имеют методы
__eq__()
и__hash__()
; с ними все объекты сравниваются неравными (кроме самих себя), аx.__hash__()
возвращает соответствующее значение, такое, чтоx == y
подразумевает какx is y
, так иhash(x) == hash(y)
.Класс, который переопределяет
__eq__()
и не определяет__hash__()
, будет иметь__hash__()
неявно установленныйNone
. Если метод__hash__()
класса имеет значениеNone
, экземпляры класса будут выдавать соответствующее сообщениеTypeError
при попытке программы получить их хэш-значение, а также будут правильно определяться как нехэшируемые при проверкеisinstance(obj, collections.abc.Hashable)
.Если класс, который переопределяет
__eq__()
, должен сохранить реализацию__hash__()
от родительского класса, интерпретатору необходимо сообщить об этом явно, установив__hash__ = <ParentClass>.__hash__
.Если класс, который не переопределяет
__eq__()
, хочет подавить поддержку хэширования, он должен включить__hash__ = None
в определение класса. Класс, определяющий свой собственный__hash__()
, который явно вызываетTypeError
, будет неправильно идентифицирован как хэшируемый вызовомisinstance(obj, collections.abc.Hashable)
.Примечание
По умолчанию значения
__hash__()
объектов str и bytes «солятся» непредсказуемым случайным значением. Хотя они остаются постоянными в рамках отдельного процесса Python, они не предсказуемы между повторными вызовами Python.Это предназначено для обеспечения защиты от отказа в обслуживании, вызванного тщательно подобранными входными данными, которые используют наихудшую производительность вставки диктанта, сложность O(n2). Подробности см. на http://www.ocert.org/advisories/ocert-2011-003.html.
Изменение хэш-значений влияет на порядок итерации множеств. Python никогда не давал гарантий относительно этого порядка (и он обычно различается между 32-битными и 64-битными сборками).
См. также
PYTHONHASHSEED
.Изменено в версии 3.3: Рандомизация хэша включена по умолчанию.
-
object.
__bool__
(self)¶ Вызывается для реализации проверки истинности значения и встроенной операции
bool()
; должен возвращатьFalse
илиTrue
. Когда этот метод не определен, вызывается__len__()
, если он определен, и объект считается истинным, если его результат ненулевой. Если класс не определяет ни__len__()
, ни__bool__()
, все его экземпляры считаются истинными.
3.3.2. Настройка доступа к атрибутам¶
Следующие методы могут быть определены для настройки значения доступа к атрибутам (использование, присвоение или удаление x.name
) для экземпляров класса.
-
object.
__getattr__
(self, name)¶ Вызывается, когда доступ к атрибуту по умолчанию не работает с ошибкой
AttributeError
(либо__getattribute__()
вызываетAttributeError
, потому что name не является атрибутом экземпляра или атрибутом в дереве класса дляself
; либо__get__()
свойства name вызываетAttributeError
). Этот метод должен либо вернуть (вычисленное) значение атрибута, либо выдать исключениеAttributeError
.Обратите внимание, что если атрибут найден с помощью обычного механизма,
__getattr__()
не вызывается. (Это намеренная асимметрия между__getattr__()
и__setattr__()
) Это сделано как из соображений эффективности, так и потому, что иначе__getattr__()
не имел бы возможности получить доступ к другим атрибутам экземпляра. Обратите внимание, что по крайней мере для переменных экземпляра можно сымитировать полный контроль, не вставляя никаких значений в словарь атрибутов экземпляра (а вместо этого вставляя их в другой объект). О том, как действительно получить полный контроль над доступом к атрибутам, смотрите метод__getattribute__()
ниже.
-
object.
__getattribute__
(self, name)¶ Вызывается безусловно для реализации доступа к атрибутам для экземпляров класса. Если класс также определяет
__getattr__()
, последний не будет вызываться, пока__getattribute__()
не вызовет его явно или не вызоветAttributeError
. Этот метод должен вернуть (вычисленное) значение атрибута или вызвать исключениеAttributeError
. Чтобы избежать бесконечной рекурсии в этом методе, его реализация должна всегда вызывать одноименный метод базового класса для доступа к любым необходимым ей атрибутам, например,object.__getattribute__(self, name)
.Примечание
Этот метод можно обойти при поиске специальных методов в результате неявного вызова через синтаксис языка или встроенные функции. См. Поиск специального метода.
Вызывает auditing event
object.__getattr__
с аргументамиobj
,name
.
-
object.
__setattr__
(self, name, value)¶ Вызывается при попытке присвоения атрибута. Вызывается вместо обычного механизма (т.е. сохранения значения в словаре экземпляра). name - имя атрибута, value - значение, которое должно быть ему присвоено.
Если
__setattr__()
хочет присвоить атрибут экземпляра, он должен вызвать метод базового класса с тем же именем, например,object.__setattr__(self, name, value)
.Вызывает auditing event
object.__setattr__
с аргументамиobj
,name
,value
.
-
object.
__delattr__
(self, name)¶ Аналогично
__setattr__()
, но для удаления атрибутов вместо присвоения. Это должно быть реализовано только в том случае, еслиdel obj.name
имеет смысл для объекта.Вызывает auditing event
object.__delattr__
с аргументамиobj
,name
.
-
object.
__dir__
(self)¶ Вызывается при вызове
dir()
на объекте. Должна быть возвращена последовательность.dir()
преобразует возвращаемую последовательность в список и сортирует его.
3.3.2.1. Настройка доступа к атрибутам модуля¶
Специальные имена __getattr__
и __dir__
также могут быть использованы для настройки доступа к атрибутам модуля. Функция __getattr__
на уровне модуля должна принимать один аргумент, который является именем атрибута, и возвращать вычисленное значение или вызывать предупреждение AttributeError
. Если атрибут не найден на объекте модуля обычным поиском, т.е. object.__getattribute__()
, то __getattr__
ищется в модуле __dict__
, прежде чем вызвать AttributeError
. Если он найден, то вызывается с именем атрибута и возвращается результат.
Функция __dir__
должна принимать никаких аргументов и возвращать последовательность строк, представляющих имена, доступные на модуле. Если эта функция присутствует, она отменяет стандартный поиск dir()
на модуле.
Для более тонкой настройки поведения модуля (установка атрибутов, свойств и т.д.) можно установить атрибут __class__
объекта модуля в подкласс types.ModuleType
. Например:
import sys
from types import ModuleType
class VerboseModule(ModuleType):
def __repr__(self):
return f'Verbose {self.__name__}'
def __setattr__(self, attr, value):
print(f'Setting {attr}...')
super().__setattr__(attr, value)
sys.modules[__name__].__class__ = VerboseModule
Примечание
Определение модуля __getattr__
и установка модуля __class__
влияют только на поиск, выполненный с использованием синтаксиса доступа к атрибутам - прямое обращение к глобальным файлам модуля (будь то код внутри модуля или ссылка на словарь глобальных файлов модуля) не влияет.
Изменено в версии 3.5: Атрибут модуля __class__
теперь доступен для записи.
Добавлено в версии 3.7: __getattr__
и __dir__
атрибуты модуля.
См.также
- PEP 562 - Модуль __getattr__ и __dir__
Описывает функции
__getattr__
и__dir__
на модулях.
3.3.2.2. Реализация дескрипторов¶
Следующие методы применяются только тогда, когда экземпляр класса, содержащего метод (так называемый класс дескриптор), появляется в классе владельца (дескриптор должен находиться либо в словаре классов владельца, либо в словаре классов одного из его родителей). В приведенных ниже примерах «атрибут» относится к атрибуту, имя которого является ключом свойства в классе-владельце __dict__
.
-
object.
__get__
(self, instance, owner=None)¶ Вызывается для получения атрибута класса-владельца (доступ к атрибуту класса) или экземпляра этого класса (доступ к атрибуту экземпляра). Необязательным аргументом owner является класс-владелец, а instance - экземпляр, через который был получен доступ к атрибуту, или
None
, если доступ к атрибуту осуществляется через owner.Этот метод должен вернуть вычисленное значение атрибута или выдать исключение
AttributeError
.PEP 252 указывает, что
__get__()
может вызываться с одним или двумя аргументами. Встроенные дескрипторы Python поддерживают эту спецификацию; однако, вероятно, некоторые сторонние инструменты имеют дескрипторы, требующие оба аргумента. Собственная реализация Python__getattribute__()
всегда передает оба аргумента, независимо от того, требуются они или нет.
-
object.
__set__
(self, instance, value)¶ Вызывается для установки атрибута на экземпляре instance класса-владельца в новое значение, value.
Обратите внимание, что добавление
__set__()
или__delete__()
изменяет тип дескриптора на «дескриптор данных». Более подробную информацию смотрите в Вызов дескрипторов.
-
object.
__delete__
(self, instance)¶ Вызывается для удаления атрибута на экземпляре экземпляре класса-владельца.
Атрибут __objclass__
интерпретируется модулем inspect
как указание класса, в котором был определен данный объект (соответствующая установка этого атрибута может помочь в интроспекции динамических атрибутов класса во время выполнения). Для вызываемых объектов он может указывать, что в качестве первого позиционного аргумента ожидается или требуется экземпляр данного типа (или подкласса) (например, CPython устанавливает этот атрибут для несвязанных методов, реализованных на C).
3.3.2.3. Вызов дескрипторов¶
В общем случае дескриптор - это атрибут объекта с «поведением привязки», доступ к атрибуту которого переопределен методами протокола дескриптора: __get__()
, __set__()
и __delete__()
. Если любой из этих методов определен для объекта, говорят, что он является дескриптором.
Поведение по умолчанию для доступа к атрибутам заключается в получении, установке или удалении атрибута из словаря объекта. Например, a.x
имеет цепочку поиска, начинающуюся с a.__dict__['x']
, затем type(a).__dict__['x']
и далее через базовые классы type(a)
, исключая метаклассы.
Однако, если искомое значение является объектом, определяющим один из методов дескриптора, то Python может отменить поведение по умолчанию и вызвать метод дескриптора вместо него. Место этого в цепочке старшинства зависит от того, какие методы дескриптора были определены и как они были вызваны.
Отправной точкой для вызова дескриптора является привязка, a.x
. То, как будут собраны аргументы, зависит от a
:
- Прямой звонок
Самый простой и наименее распространенный вызов - это когда пользовательский код напрямую вызывает метод дескриптора:
x.__get__(a)
.- Привязка к экземпляру
При привязке к экземпляру объекта
a.x
преобразуется в вызов:type(a).__dict__['x'].__get__(a, type(a))
.- Привязка к классу
Если привязка к классу,
A.x
преобразуется в вызов:A.__dict__['x'].__get__(None, A)
.- Суперпереплет
Если
a
является экземпляромsuper
, то связываниеsuper(B, obj).m()
ищетobj.__class__.__mro__
базовый классA
сразу послеB
и затем вызывает дескриптор с вызовом:A.__dict__['m'].__get__(obj, obj.__class__)
.
Для привязок экземпляров приоритет вызова дескриптора зависит от того, какие методы дескриптора определены. Дескриптор может определять любую комбинацию __get__()
, __set__()
и __delete__()
. Если он не определяет __get__()
, то обращение к атрибуту вернет сам объект дескриптора, если только в словаре экземпляров объекта нет значения. Если дескриптор определяет __set__()
и/или __delete__()
, то он является дескриптором данных; если он не определяет ни одного из них, то он является дескриптором не данных. Обычно дескрипторы данных определяют и __get__()
, и __set__()
, в то время как дескрипторы не данных имеют только метод __get__()
. Дескрипторы данных с определенными __get__()
и __set__()
(и/или __delete__()
) всегда переопределяют переопределение в словаре экземпляров. В отличие от этого, дескрипторы, не относящиеся к данным, могут быть переопределены экземплярами.
Методы Python (включая методы, украшенные символами @staticmethod
и @classmethod
) реализованы как дескрипторы, не содержащие данных. Соответственно, экземпляры могут переопределять и переопределять методы. Это позволяет отдельным экземплярам приобретать поведение, отличающееся от поведения других экземпляров того же класса.
Функция property()
реализована как дескриптор данных. Соответственно, экземпляры не могут переопределять поведение свойства.
3.3.2.4. __слоты__¶
__slots__ позволяют нам явно объявлять члены данных (например, свойства) и запрещают создание __dict__
и __weakref__ (если они явно не объявлены в __slots__ или не доступны в родителе).
Экономия места по сравнению с использованием __dict__
может быть значительной. Скорость поиска атрибутов также может быть значительно улучшена.
-
object.
__slots__
¶ Этой переменной класса может быть присвоена строка, итерабельность или последовательность строк с именами переменных, используемых экземплярами. __slots__ резервирует место для объявленных переменных и предотвращает автоматическое создание
__dict__
и __weakref__ для каждого экземпляра.
3.3.2.4.1. Указания по использованию __slots__.¶
При наследовании от класса без __slots__ атрибут
__dict__
и __weakref__ экземпляров всегда будут доступны.Без переменной
__dict__
экземпляры не могут быть назначены новым переменным, не перечисленным в определении __slots__. Попытки присвоить имя переменной, не включенной в список, вызывают ошибкуAttributeError
. Если необходимо динамическое присвоение новых переменных, то добавьте'__dict__'
к последовательности строк в объявлении __slots__.Без переменной __weakref__ для каждого экземпляра классы, определяющие __slots__, не поддерживают
weak references
к своим экземплярам. Если поддержка слабых ссылок необходима, то добавьте'__weakref__'
к последовательности строк в объявлении __slots__.__slots__ реализованы на уровне класса путем создания descriptors для каждого имени переменной. В результате атрибуты класса не могут быть использованы для установки значений по умолчанию для переменных экземпляра, определенных __slots__; в противном случае атрибут класса перезапишет назначение дескриптора.
Действие объявления __slots__ не ограничивается классом, в котором оно определено. Объявленные в родительском классе __slots__ доступны в дочерних классах. Однако дочерние подклассы получат
__dict__
и __weakref__, если они также не определят __slots__ (которые должны содержать только имена любых дополнительных слотов).Если класс определяет слот, определенный также в базовом классе, переменная экземпляра, определенная слотом базового класса, становится недоступной (за исключением получения ее дескриптора непосредственно из базового класса). Это делает смысл программы неопределенным. В будущем может быть добавлена проверка для предотвращения этого.
Непустые __slots__ не работают для классов, производных от встроенных типов «переменной длины», таких как
int
,bytes
иtuple
.Любая нестрока iterable может быть назначена на __slots__.
Если для назначения __слотов__ используется
dictionary
, ключи словаря будут использоваться в качестве имен слотов. Значения словаря могут быть использованы для предоставления докстрок по каждому атрибуту, которые будут распознаныinspect.getdoc()
и отображены в выводеhelp()
.Назначение
__class__
работает, только если оба класса имеют одинаковые __slots__.Multiple inheritance можно использовать несколько родительских классов со слотами, но только один родитель может иметь атрибуты, созданные слотами (остальные базы должны иметь пустые макеты слотов) - нарушения вызывают ошибку
TypeError
.Если для __slots__ используется iterator, то для каждого значения итератора создается descriptor. Однако атрибут __slots__ будет пустым итератором.
3.3.3. Настройка создания классов¶
Всякий раз, когда класс наследуется от другого класса, __init_subclass__()
вызывается на родительском классе. Таким образом, можно писать классы, которые изменяют поведение подклассов. Это тесно связано с декораторами классов, но если декораторы классов влияют только на конкретный класс, к которому они применяются, то __init_subclass__
применяется только к будущим подклассам класса, определяющего метод.
-
classmethod
object.
__init_subclass__
(cls)¶ Этот метод вызывается всякий раз, когда содержащий класс становится подклассом. В этом случае cls является новым подклассом. Если этот метод определен как обычный метод экземпляра, он неявно преобразуется в метод класса.
Аргументы ключевых слов, которые передаются новому классу, передаются родительскому классу
__init_subclass__
. Для совместимости с другими классами, использующими__init_subclass__
, следует убрать нужные аргументы ключевых слов, а остальные передать базовому классу, как в:class Philosopher: def __init_subclass__(cls, /, default_name, **kwargs): super().__init_subclass__(**kwargs) cls.default_name = default_name class AustralianPhilosopher(Philosopher, default_name="Bruce"): pass
Реализация по умолчанию
object.__init_subclass__
ничего не делает, но вызывает ошибку, если она вызвана с какими-либо аргументами.Примечание
Подсказка метакласса
metaclass
потребляется остальной частью механизма типов и никогда не передается реализациям__init_subclass__
. Доступ к собственно метаклассу (а не к явной подсказке) можно получить какtype(cls)
.Добавлено в версии 3.6.
Когда создается класс, type.__new__()
сканирует переменные класса и выполняет обратные вызовы к ним с помощью хука __set_name__()
.
-
object.
__set_name__
(self, owner, name)¶ Автоматически вызывается в момент создания класса-владельца owner. Объект был назначен на имя в этом классе:
class A: x = C() # Automatically calls: x.__set_name__(A, 'x')
Если переменная класса назначена после создания класса,
__set_name__()
не будет вызвана автоматически. При необходимости__set_name__()
может быть вызван напрямую:class A: pass c = C() A.x = c # The hook is not called c.__set_name__(A, 'x') # Manually invoke the hook
Более подробную информацию см. в разделе Создание объекта класса.
Добавлено в версии 3.6.
3.3.3.1. Метаклассы¶
По умолчанию классы конструируются с помощью type()
. Тело класса выполняется в новом пространстве имен, а имя класса привязывается локально к результату type(name, bases, namespace)
.
Процесс создания класса можно настроить, передав аргумент с ключевым словом metaclass
в строке определения класса, или унаследовав от существующего класса, который включает такой аргумент. В следующем примере оба класса MyClass
и MySubclass
являются экземплярами класса Meta
:
class Meta(type):
pass
class MyClass(metaclass=Meta):
pass
class MySubclass(MyClass):
pass
Любые другие аргументы ключевых слов, указанные в определении класса, передаются во все операции с метаклассом, описанные ниже.
Когда выполняется определение класса, происходят следующие действия:
Записи по ТОиР разрешены;
определяется соответствующий метакласс;
пространство имен класса подготовлено;
выполняется тело класса;
создается объект класса.
3.3.3.2. Урегулирование записей по ТОиР¶
Если база, фигурирующая в определении класса, не является экземпляром type
, то для нее ищется метод __mro_entries__
. Если он найден, то он вызывается с исходным кортежем баз. Этот метод должен вернуть кортеж классов, которые будут использоваться вместо данной базы. Кортеж может быть пустым, в этом случае исходная база игнорируется.
См.также
PEP 560 - Поддержка ядра для типизации модульных и общих типов
3.3.3.3. Определение подходящего метакласса¶
Подходящий метакласс для определения класса определяется следующим образом:
если не указаны базы и явный метакласс, то используется
type()
;если указан явный метакласс и он не является экземпляром
type()
, то он используется непосредственно как метакласс;если в качестве явного метакласса указан экземпляр
type()
, или определены базы, то используется наиболее производный метакласс.
Наиболее производный метакласс выбирается из явно указанного метакласса (если таковой имеется) и метаклассов (т.е. type(cls)
) всех указанных базовых классов. Самый производный метакласс - это тот, который является подтипом всех этих кандидатов в метаклассы. Если ни один из метаклассов-кандидатов не удовлетворяет этому критерию, то определение класса завершится неудачей с ошибкой TypeError
.
3.3.3.4. Подготовка пространства имен класса¶
После определения подходящего метакласса подготавливается пространство имен класса. Если метакласс имеет атрибут __prepare__
, то он вызывается как namespace = metaclass.__prepare__(name, bases, **kwds)
(где дополнительные аргументы ключевого слова, если таковые имеются, берутся из определения класса). Метод __prepare__
должен быть реализован как classmethod
. Пространство имен, возвращаемое __prepare__
, передается в __new__
, но при создании конечного объекта класса пространство имен копируется в новое dict
.
Если у метакласса нет атрибута __prepare__
, то пространство имен класса инициализируется как пустое упорядоченное отображение.
См.также
- PEP 3115 - Метаклассы в Python 3000
Введен крючок пространства имен
__prepare__
3.3.3.5. Выполнение тела класса¶
Тело класса выполняется (приблизительно) как exec(body, globals(), namespace)
. Ключевое отличие от обычного вызова exec()
заключается в том, что лексическая область видимости позволяет телу класса (включая любые методы) ссылаться на имена из текущей и внешней областей видимости, когда определение класса происходит внутри функции.
Однако даже если определение класса происходит внутри функции, методы, определенные внутри класса, все равно не могут видеть имена, определенные в области видимости класса. Доступ к переменным класса должен осуществляться через первый параметр методов экземпляра или класса или через неявную лексически развернутую ссылку __class__
, описанную в следующем разделе.
3.3.3.6. Создание объекта класса¶
После заполнения пространства имен класса путем выполнения тела класса, объект класса создается вызовом metaclass(name, bases, namespace, **kwds)
(дополнительные ключевые слова, передаваемые здесь, такие же, как и в __prepare__
).
Именно на этот объект класса будет ссылаться нулевой аргумент формы super()
. __class__
- это неявная закрывающая ссылка, создаваемая компилятором, если какие-либо методы в теле класса ссылаются на __class__
или super
. Это позволяет форме с нулевым аргументом super()
правильно идентифицировать определяемый класс на основе лексического анализа, в то время как класс или экземпляр, который был использован для текущего вызова, идентифицируется на основе первого аргумента, переданного методу.
CPython implementation detail: В CPython 3.6 и более поздних версиях ячейка __class__
передается в метакласс как запись __classcell__
в пространстве имен класса. Если она присутствует, она должна быть распространена до вызова type.__new__
, чтобы класс был инициализирован правильно. Если этого не сделать, то в Python 3.8 это приведет к ошибке RuntimeError
.
При использовании метакласса по умолчанию type
или любого метакласса, который в конечном итоге вызывает type.__new__
, после создания объекта класса вызываются следующие дополнительные шаги настройки:
Метод
type.__new__
собирает все атрибуты в пространстве имен класса, которые определяют метод__set_name__()
;Эти методы
__set_name__
вызываются с помощью определяемого класса и присвоенного имени конкретного атрибута;Хук
__init_subclass__()
вызывается на непосредственном родителе нового класса в порядке разрешения его методов.
После создания объекта класса он передается декораторам класса, включенным в определение класса (если таковые имеются), и полученный объект привязывается в локальном пространстве имен как определенный класс.
Когда новый класс создается с помощью type.__new__
, объект, предоставленный в качестве параметра пространства имен, копируется в новое упорядоченное отображение, а исходный объект отбрасывается. Новая копия оборачивается в доступный только для чтения прокси, который становится атрибутом __dict__
объекта класса.
См.также
- PEP 3135 - Новый супер
Описывает неявную ссылку на закрытие
__class__
3.3.3.7. Использование метаклассов¶
Потенциальные возможности использования метаклассов безграничны. Некоторые идеи, которые были изучены, включают в себя перечисление, протоколирование, проверку интерфейса, автоматическое делегирование, автоматическое создание свойств, прокси, фреймворки и автоматическую блокировку/синхронизацию ресурсов.
3.3.4. Настройка проверок экземпляров и подклассов¶
Следующие методы используются для переопределения поведения по умолчанию встроенных функций isinstance()
и issubclass()
.
В частности, метакласс abc.ABCMeta
реализует эти методы, чтобы позволить добавлять абстрактные базовые классы (ABC) в качестве «виртуальных базовых классов» к любому классу или типу (включая встроенные типы), включая другие ABC.
-
class.
__instancecheck__
(self, instance)¶ Возвращает true, если instance следует считать (прямым или косвенным) экземпляром class. Если определено, вызывается для реализации
isinstance(instance, class)
.
-
class.
__subclasscheck__
(self, subclass)¶ Возвращает true, если subclass следует считать (прямым или косвенным) подклассом class. Если определено, вызывается для реализации
issubclass(subclass, class)
.
Обратите внимание, что эти методы ищутся в типе (метаклассе) класса. Они не могут быть определены как методы класса в самом классе. Это соответствует поиску специальных методов, которые вызываются на экземплярах, только в этом случае экземпляр сам является классом.
См.также
- PEP 3119 - Представление абстрактных базовых классов
Включает спецификацию для настройки поведения
isinstance()
иissubclass()
посредством__instancecheck__()
и__subclasscheck__()
, с мотивацией этой функциональности в контексте добавления в язык абстрактных базовых классов (см. модульabc
).
3.3.5. Эмуляция общих типов¶
При использовании type annotations часто полезно параметризировать generic type, используя нотацию квадратных скобок Python. Например, аннотация list[int]
может быть использована для обозначения list
, в котором все элементы имеют тип int
.
См.также
- PEP 484 - Подсказки типа
Знакомство с основой Python для аннотаций типов
- Generic Alias Types
Документация для объектов, представляющих параметризованные общие классы
- Дженерики, user-defined generics и
typing.Generic
. Документация о том, как реализовать общие классы, которые могут быть параметризованы во время выполнения и понятны статическим средствам проверки типов.
Класс может обычно быть параметризованным, только если он определяет специальный метод класса __class_getitem__()
.
-
classmethod
object.
__class_getitem__
(cls, key)¶ Возвращает объект, представляющий специализацию общего класса по аргументам типа, найденным в key.
Если метод определен для класса,
__class_getitem__()
автоматически является методом класса. Поэтому при его определении нет необходимости украшать его символом@classmethod
.
3.3.5.1. Назначение __class_getitem__.¶
Цель __class_getitem__()
состоит в том, чтобы позволить параметризацию стандартно-библиотечных общих классов во время выполнения, чтобы легче применять type hints к этим классам.
Для реализации пользовательских общих классов, которые могут быть параметризованы во время выполнения и поняты статическими средствами проверки типов, пользователи должны либо наследоваться от класса стандартной библиотеки, который уже реализует __class_getitem__()
, либо наследоваться от typing.Generic
, который имеет свою собственную реализацию __class_getitem__()
.
Пользовательские реализации __class_getitem__()
на классах, определенных вне стандартной библиотеки, могут быть не поняты сторонними программами проверки типов, такими как mypy. Использование __class_getitem__()
в любом классе для целей, отличных от подсказки типов, не рекомендуется.
3.3.5.2. __class_getitem__ против __getitem__.¶
Обычно subscription объекта с использованием квадратных скобок вызывает метод экземпляра __getitem__()
, определенный в классе объекта. Однако, если подписываемый объект сам является классом, вместо него может быть вызван метод класса __class_getitem__()
. __class_getitem__()
должен возвращать объект GenericAlias, если он правильно определен.
Представленный expression obj[x]
, интерпретатор Python выполняет примерно следующий процесс, чтобы решить, следует ли вызвать __getitem__()
или __class_getitem__()
:
from inspect import isclass
def subscribe(obj, x):
"""Return the result of the expression `obj[x]`"""
class_of_obj = type(obj)
# If the class of obj defines __getitem__,
# call class_of_obj.__getitem__(obj, x)
if hasattr(class_of_obj, '__getitem__'):
return class_of_obj.__getitem__(obj, x)
# Else, if obj is a class and defines __class_getitem__,
# call obj.__class_getitem__(x)
elif isclass(obj) and hasattr(obj, '__class_getitem__'):
return obj.__class_getitem__(x)
# Else, raise an exception
else:
raise TypeError(
f"'{class_of_obj.__name__}' object is not subscriptable"
)
В Python все классы сами являются экземплярами других классов. Класс класса известен как metaclass, а большинство классов имеют класс type
в качестве своего метакласса. type
не определяет __getitem__()
, что означает, что такие выражения, как list[int]
, dict[str, float]
и tuple[str, bytes]
приводят к вызову __class_getitem__()
:
>>> # list has class "type" as its metaclass, like most classes:
>>> type(list)
<class 'type'>
>>> type(dict) == type(list) == type(tuple) == type(str) == type(bytes)
True
>>> # "list[int]" calls "list.__class_getitem__(int)"
>>> list[int]
list[int]
>>> # list.__class_getitem__ returns a GenericAlias object:
>>> type(list[int])
<class 'types.GenericAlias'>
Однако, если класс имеет пользовательский метакласс, определяющий __getitem__()
, подписка на него может привести к другому поведению. Пример этого можно найти в модуле enum
:
>>> from enum import Enum
>>> class Menu(Enum):
... """A breakfast menu"""
... SPAM = 'spam'
... BACON = 'bacon'
...
>>> # Enum classes have a custom metaclass:
>>> type(Menu)
<class 'enum.EnumMeta'>
>>> # EnumMeta defines __getitem__,
>>> # so __class_getitem__ is not called,
>>> # and the result is not a GenericAlias object:
>>> Menu['SPAM']
<Menu.SPAM: 'spam'>
>>> type(Menu['SPAM'])
<enum 'Menu'>
См.также
- PEP 560 - Ядро Поддержка типизации модульных и общих типов
Представляем
__class_getitem__()
и описываем, когда subscription приводит к тому, что вместо__class_getitem__()
вызывается__getitem__()
3.3.6. Эмуляция вызываемых объектов¶
-
object.
__call__
(self[, args...])¶ Вызывается, когда экземпляр «вызывается» как функция; если этот метод определен,
x(arg1, arg2, ...)
примерно переводится какtype(x).__call__(x, arg1, ...)
.
3.3.7. Эмуляция типов контейнеров¶
Следующие методы могут быть определены для реализации объектов контейнеров. Контейнеры обычно представляют собой sequences (такие как lists
или tuples
) или mappings (такие как dictionaries
), но могут представлять и другие контейнеры. Первый набор методов используется либо для эмуляции последовательности, либо для эмуляции отображения; разница в том, что для последовательности допустимыми ключами должны быть целые числа k, для которых 0 <= k < N
, где N - длина последовательности, или объекты slice
, которые определяют диапазон элементов. Также рекомендуется, чтобы отображения предоставляли методы keys()
, values()
, items()
, get()
, clear()
, setdefault()
, pop()
, popitem()
, copy()
и update()
, которые ведут себя аналогично методам для стандартных объектов Python dictionary
. Модуль collections.abc
предоставляет MutableMapping
abstract base class, чтобы помочь создать эти методы из базового набора __getitem__()
, __setitem__()
, __delitem__()
и keys()
. Мутабельные последовательности должны предоставлять методы append()
, count()
, index()
, extend()
, insert()
, pop()
, remove()
, reverse()
и sort()
, как стандартные объекты Python list
. Наконец, типы последовательности должны реализовывать сложение (то есть конкатенацию) и умножение (то есть повторение) путем определения методов __add__()
, __radd__()
, __iadd__()
, __mul__()
, __rmul__()
и __imul__()
, описанных ниже; они не должны определять другие числовые операторы. Рекомендуется, чтобы и отображения, и последовательности реализовывали метод __contains__()
для эффективного использования оператора in
; для отображений in
должен искать ключи отображения; для последовательностей он должен искать по значениям. Кроме того, рекомендуется, чтобы и отображения, и последовательности реализовывали метод __iter__()
, чтобы обеспечить эффективную итерацию по контейнеру; для отображений __iter__()
должен выполнять итерацию по ключам объекта, а для последовательностей - по значениям.
-
object.
__len__
(self)¶ Вызывается для реализации встроенной функции
len()
. Должна возвращать длину объекта, целое число>=
0. Также объект, который не определяет метод__bool__()
и чей метод__len__()
возвращает ноль, считается ложным в булевом контексте.CPython implementation detail: В CPython требуется, чтобы длина была не более
sys.maxsize
. Если длина большеsys.maxsize
, некоторые функции (например,len()
) могут выдатьOverflowError
. Чтобы предотвратить возникновениеOverflowError
при проверке истинности значения, объект должен определить метод__bool__()
.
-
object.
__length_hint__
(self)¶ Вызывается для реализации
operator.length_hint()
. Должна вернуть предполагаемую длину объекта (которая может быть больше или меньше фактической длины). Длина должна быть целым числом>=
0. Возвращаемое значение также может бытьNotImplemented
, что рассматривается так же, как если бы метод__length_hint__
вообще не существовал. Этот метод является исключительно оптимизацией и никогда не требуется для корректности.Добавлено в версии 3.4.
Примечание
Нарезка выполняется исключительно с помощью следующих трех методов. Вызов типа
a[1:2] = b
переводится как
a[slice(1, 2, None)] = b
и так далее. Пропущенные элементы среза всегда заполняются символом None
.
-
object.
__getitem__
(self, key)¶ Вызывается для реализации оценки
self[key]
. Для типов sequence принятыми ключами должны быть целые числа и объекты slice. Обратите внимание, что специальная интерпретация отрицательных индексов (если класс хочет эмулировать тип sequence) зависит от метода__getitem__()
. Если key имеет неподходящий тип, может возникнуть ошибкаTypeError
; если значение вне набора индексов для последовательности (после любой специальной интерпретации отрицательных значений), должна возникнуть ошибкаIndexError
. Для типов mapping, если key отсутствует (нет в контейнере), должно быть вызвано сообщениеKeyError
.Примечание
Циклы
for
ожидают, что для недопустимых индексов будет вызван сигналIndexError
, чтобы правильно определить конец последовательности.Примечание
Когда subscripting является классом, вместо
__class_getitem__()
может быть вызван специальный метод класса__getitem__()
. Более подробную информацию см. в разделе __class_getitem__ против __getitem__..
-
object.
__setitem__
(self, key, value)¶ Вызывается для реализации присваивания в
self[key]
. То же замечание, что и для__getitem__()
. Это должно быть реализовано только для отображений, если объекты поддерживают изменения значений ключей, или если могут быть добавлены новые ключи, или для последовательностей, если элементы могут быть заменены. Для неправильных значений ключей должны возникать те же исключения, что и для метода__getitem__()
.
-
object.
__delitem__
(self, key)¶ Вызывается для реализации удаления
self[key]
. То же замечание, что и для__getitem__()
. Это должно быть реализовано только для отображений, если объекты поддерживают удаление ключей, или для последовательностей, если элементы могут быть удалены из последовательности. Для неправильных значений ключей должны возникать те же исключения, что и для метода__getitem__()
.
-
object.
__missing__
(self, key)¶ Вызывается
dict
.__getitem__()
для реализацииself[key]
для подклассов dict, когда ключ не находится в словаре.
-
object.
__iter__
(self)¶ Этот метод вызывается, когда для контейнера требуется iterator. Этот метод должен возвращать новый объект-итератор, который может выполнять итерацию по всем объектам в контейнере. Для отображений он должен перебирать ключи контейнера.
-
object.
__reversed__
(self)¶ Вызывается (если присутствует) встроенным
reversed()
для реализации обратной итерации. Он должен вернуть новый объект-итератор, который выполняет итерацию по всем объектам в контейнере в обратном порядке.Если метод
__reversed__()
не предоставлен, встроенныйreversed()
вернется к использованию протокола последовательности (__len__()
и__getitem__()
). Объекты, поддерживающие протокол последовательности, должны предоставлять__reversed__()
только в том случае, если они могут предоставить реализацию, более эффективную, чем та, которую предоставляетreversed()
.
Операторы проверки принадлежности (in
и not in
) обычно реализуются как итерация по контейнеру. Однако объекты-контейнеры могут предоставить следующий специальный метод с более эффективной реализацией, который также не требует, чтобы объект был итерируемым.
-
object.
__contains__
(self, item)¶ Вызывается для реализации операторов проверки принадлежности. Должен возвращать true, если item находится в self, false в противном случае. Для объектов отображения следует учитывать ключи отображения, а не значения или пары ключ-элемент.
Для объектов, которые не определяют
__contains__()
, тест членства сначала пробует итерацию через__iter__()
, затем старый протокол итерации последовательности через__getitem__()
, см. this section in the language reference.
3.3.8. Эмуляция числовых типов¶
Для эмуляции числовых объектов могут быть определены следующие методы. Методы, соответствующие операциям, которые не поддерживаются конкретным видом реализуемого числа (например, побитовые операции для неинтегральных чисел), следует оставить неопределенными.
-
object.
__add__
(self, other)¶ -
object.
__sub__
(self, other)¶ -
object.
__mul__
(self, other)¶ -
object.
__matmul__
(self, other)¶ -
object.
__truediv__
(self, other)¶ -
object.
__floordiv__
(self, other)¶ -
object.
__mod__
(self, other)¶ -
object.
__divmod__
(self, other)¶ -
object.
__pow__
(self, other[, modulo])¶ -
object.
__lshift__
(self, other)¶ -
object.
__rshift__
(self, other)¶ -
object.
__and__
(self, other)¶ -
object.
__xor__
(self, other)¶ -
object.
__or__
(self, other)¶ Эти методы вызываются для реализации операций двоичной арифметики (
+
,-
,*
,@
,/
,//
,%
,divmod()
,pow()
,**
,<<
,>>
,&
,^
,|
). Например, для оценки выраженияx + y
, где x - экземпляр класса, имеющего метод__add__()
, вызываетсяx.__add__(y)
. Метод__divmod__()
должен быть эквивалентен использованию__floordiv__()
и__mod__()
; он не должен быть связан с__truediv__()
. Обратите внимание, что__pow__()
должен быть определен для приема необязательного третьего аргумента, если поддерживается троичная версия встроенной функцииpow()
.Если один из этих методов не поддерживает операцию с предоставленными аргументами, он должен вернуть
NotImplemented
.
-
object.
__radd__
(self, other)¶ -
object.
__rsub__
(self, other)¶ -
object.
__rmul__
(self, other)¶ -
object.
__rmatmul__
(self, other)¶ -
object.
__rtruediv__
(self, other)¶ -
object.
__rfloordiv__
(self, other)¶ -
object.
__rmod__
(self, other)¶ -
object.
__rdivmod__
(self, other)¶ -
object.
__rpow__
(self, other[, modulo])¶ -
object.
__rlshift__
(self, other)¶ -
object.
__rrshift__
(self, other)¶ -
object.
__rand__
(self, other)¶ -
object.
__rxor__
(self, other)¶ -
object.
__ror__
(self, other)¶ Эти методы вызываются для реализации операций двоичной арифметики (
+
,-
,*
,@
,/
,//
,%
,divmod()
,pow()
,**
,<<
,>>
,&
,^
,|
) с отраженными (поменявшимися местами) операндами. Эти функции вызываются только в том случае, если левый операнд не поддерживает соответствующую операцию 3 и операнды имеют разные типы. 4 Например, для оценки выраженияx - y
, где y - экземпляр класса, имеющего метод__rsub__()
, вызываетсяy.__rsub__(x)
, еслиx.__sub__(y)
возвращает NotImplemented.Обратите внимание, что троичный
pow()
не будет пытаться вызвать__rpow__()
(правила принуждения стали бы слишком сложными).Примечание
Если тип правого операнда является подклассом типа левого операнда и этот подкласс предоставляет другую реализацию отраженного метода для операции, этот метод будет вызван перед неотраженным методом левого операнда. Такое поведение позволяет подклассам переопределять операции своих предков.
-
object.
__iadd__
(self, other)¶ -
object.
__isub__
(self, other)¶ -
object.
__imul__
(self, other)¶ -
object.
__imatmul__
(self, other)¶ -
object.
__itruediv__
(self, other)¶ -
object.
__ifloordiv__
(self, other)¶ -
object.
__imod__
(self, other)¶ -
object.
__ipow__
(self, other[, modulo])¶ -
object.
__ilshift__
(self, other)¶ -
object.
__irshift__
(self, other)¶ -
object.
__iand__
(self, other)¶ -
object.
__ixor__
(self, other)¶ -
object.
__ior__
(self, other)¶ Эти методы вызываются для реализации дополненных арифметических присваиваний (
+=
,-=
,*=
,@=
,/=
,//=
,%=
,**=
,<<=
,>>=
,&=
,^=
,|=
). Эти методы должны пытаться выполнить операцию на месте (изменяя self) и вернуть результат (который может быть, но не обязательно должен быть self). Если конкретный метод не определен, дополненное присваивание возвращается к обычным методам. Например, если x является экземпляром класса с методом__iadd__()
, тоx += y
эквивалентноx = x.__iadd__(y)
. В противном случае рассматриваютсяx.__add__(y)
иy.__radd__(x)
, как и при оценкеx + y
. В некоторых ситуациях дополненное присваивание может привести к неожиданным ошибкам (см. Почему a_tuple[i] += [„item“] вызывает исключение, когда сложение работает?), но на самом деле такое поведение является частью модели данных.
-
object.
__neg__
(self)¶ -
object.
__pos__
(self)¶ -
object.
__abs__
(self)¶ -
object.
__invert__
(self)¶ Вызывается для реализации унарных арифметических операций (
-
,+
,abs()
и~
).
-
object.
__complex__
(self)¶ -
object.
__int__
(self)¶ -
object.
__float__
(self)¶ Вызывается для реализации встроенных функций
complex()
,int()
иfloat()
. Должно возвращаться значение соответствующего типа.
-
object.
__index__
(self)¶ Вызывается для реализации
operator.index()
, а также всякий раз, когда Python должен без потерь преобразовать числовой объект в целочисленный (например, при нарезке или во встроенных функцияхbin()
,hex()
иoct()
). Наличие этого метода указывает на то, что числовой объект является целочисленным типом. Должен возвращать целое число.Если
__int__()
,__float__()
и__complex__()
не определены, то соответствующие встроенные функцииint()
,float()
иcomplex()
возвращаются к__index__()
.
-
object.
__round__
(self[, ndigits])¶ -
object.
__trunc__
(self)¶ -
object.
__floor__
(self)¶ -
object.
__ceil__
(self)¶ Вызывается для реализации встроенной функции
round()
иmath
функцийtrunc()
,floor()
иceil()
. Если в__round__()
не передано ndigits, все эти методы должны возвращать значение объекта, усеченное доIntegral
(обычноint
).Встроенная функция
int()
возвращается к__trunc__()
, если не определены ни__int__()
, ни__index__()
.
3.3.9. С менеджерами по контексту заявлений¶
context manager - это объект, определяющий контекст времени выполнения, который должен быть создан при выполнении оператора with
. Менеджер контекста обрабатывает вход в желаемый контекст времени выполнения и выход из него для выполнения блока кода. Менеджеры контекста обычно вызываются с помощью оператора with
(описанного в разделе Оператор with), но также могут быть использованы путем прямого вызова их методов.
Типичное использование менеджеров контекста включает сохранение и восстановление различных видов глобального состояния, блокировку и разблокировку ресурсов, закрытие открытых файлов и т.д.
Для получения дополнительной информации о менеджерах контекста смотрите Типы контекстного менеджера.
-
object.
__enter__
(self)¶ Введите контекст времени выполнения, связанный с этим объектом. Оператор
with
свяжет возвращаемое значение этого метода с целью (целями), указанной в пунктеas
оператора, если таковые имеются.
-
object.
__exit__
(self, exc_type, exc_value, traceback)¶ Выход из контекста выполнения, связанного с данным объектом. Параметры описывают исключение, которое вызвало выход из контекста. Если контекст был завершен без исключения, все три аргумента будут
None
.Если подано исключение, и метод хочет подавить исключение (т.е. предотвратить его распространение), он должен вернуть значение true. В противном случае исключение будет обработано нормально при выходе из этого метода.
Обратите внимание, что методы
__exit__()
не должны поднимать переданное исключение; за это отвечает вызывающая сторона.
3.3.10. Настройка позиционных аргументов при сопоставлении шаблонов классов¶
При использовании имени класса в шаблоне позиционные аргументы в шаблоне по умолчанию не допускаются, т.е. case MyClass(x, y)
обычно недопустимо без специальной поддержки MyClass
. Чтобы иметь возможность использовать такого рода шаблоны, класс должен определить атрибут __match_args__.
-
object.
__match_args__
¶ Этой переменной класса можно присвоить кортеж строк. Когда этот класс используется в шаблоне класса с позиционными аргументами, каждый позиционный аргумент будет преобразован в аргумент ключевого слова, используя соответствующее значение в __match_args__ в качестве ключевого слова. Отсутствие этого атрибута эквивалентно его установке в
()
.
Например, если MyClass.__match_args__
является ("left", "center", "right")
, это означает, что case MyClass(x, y)
эквивалентно case MyClass(left=x, center=y)
. Обратите внимание, что количество аргументов в шаблоне должно быть меньше или равно количеству элементов в __match_args__; если оно больше, то попытка сопоставления шаблона приведет к ошибке TypeError
.
Добавлено в версии 3.10.
См.также
- PEP 634 - Структурное сопоставление шаблонов
Спецификация для оператора Python
match
.
3.3.11. Поиск специального метода¶
Для пользовательских классов неявные вызовы специальных методов гарантированно работают правильно, только если они определены в типе объекта, а не в словаре экземпляров объекта. Такое поведение является причиной того, что следующий код вызывает исключение:
>>> class C:
... pass
...
>>> c = C()
>>> c.__len__ = lambda: 5
>>> len(c)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type 'C' has no len()
Причина такого поведения кроется в ряде специальных методов, таких как __hash__()
и __repr__()
, которые реализуются всеми объектами, включая объекты типа. Если бы неявный поиск этих методов использовал обычный процесс поиска, то при вызове на самом объекте типа они бы не сработали:
>>> 1 .__hash__() == hash(1)
True
>>> int.__hash__() == hash(int)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: descriptor '__hash__' of 'int' object needs an argument
Неправильная попытка вызвать несвязанный метод класса таким образом иногда называется «путаницей метаклассов», и ее можно избежать, обходя экземпляр при поиске специальных методов:
>>> type(1).__hash__(1) == hash(1)
True
>>> type(int).__hash__(int) == hash(int)
True
В дополнение к обходу любых атрибутов экземпляра в интересах корректности, неявный поиск специального метода обычно также обходит метод __getattribute__()
даже метакласса объекта:
>>> class Meta(type):
... def __getattribute__(*args):
... print("Metaclass getattribute invoked")
... return type.__getattribute__(*args)
...
>>> class C(object, metaclass=Meta):
... def __len__(self):
... return 10
... def __getattribute__(*args):
... print("Class getattribute invoked")
... return object.__getattribute__(*args)
...
>>> c = C()
>>> c.__len__() # Explicit lookup via instance
Class getattribute invoked
10
>>> type(c).__len__(c) # Explicit lookup via type
Metaclass getattribute invoked
10
>>> len(c) # Implicit lookup
10
Обход механизма __getattribute__()
таким образом предоставляет значительные возможности для оптимизации скорости работы интерпретатора, ценой некоторой гибкости в обработке специальных методов (специальный метод должен быть установлен на самом объекте класса, чтобы интерпретатор последовательно вызывал его).
3.4. Корутины¶
3.4.1. Ожидаемые объекты¶
Объект awaitable обычно реализует метод __await__()
. Coroutine objects, возвращаемые из функций async def
, являются ожидаемыми.
Примечание
Объекты generator iterator, возвращаемые генераторами, украшенными types.coroutine()
или asyncio.coroutine()
, также ожидаемы, но они не реализуют __await__()
.
-
object.
__await__
(self)¶ Должен возвращать iterator. Должен использоваться для реализации объектов awaitable. Например,
asyncio.Future
реализует этот метод, чтобы быть совместимым с выражениемawait
.
Добавлено в версии 3.5.
См.также
PEP 492 для получения дополнительной информации об ожидаемых объектах.
3.4.2. Объекты Coroutine¶
Coroutine objects являются объектами awaitable. Выполнение короутины можно контролировать путем вызова __await__()
и итерации по результату. Когда программа завершает выполнение и возвращается, итератор вызывает StopIteration
, а атрибут исключения value
содержит возвращаемое значение. Если программа вызывает исключение, оно передается итератору. Короутины не должны напрямую вызывать необработанные исключения StopIteration
.
Короутины также имеют перечисленные ниже методы, которые аналогичны методам генераторов (см. Генераторно-итераторные методы). Однако, в отличие от генераторов, короутины не поддерживают непосредственно итерацию.
Изменено в версии 3.5.2: Ожидать выполнения coroutine более одного раза - это RuntimeError
.
-
coroutine.
send
(value)¶ Запускает или возобновляет выполнение корутины. Если value равно
None
, это эквивалентно продвижению итератора, возвращаемого методом__await__()
. Если значение не равноNone
, этот метод делегирует методsend()
тому итератору, который вызвал приостановку выполнения программы. Результат (возвращаемое значение,StopIteration
или другое исключение) такой же, как и при итерации по возвращаемому значению__await__()
, описанному выше.
-
coroutine.
throw
(value)¶ -
coroutine.
throw
(type[, value[, traceback]]) Вызывает указанное исключение в этой программе. Этот метод делегирует метод
throw()
итератора, вызвавшего приостановку программы, если у нее есть такой метод. В противном случае исключение вызывается в точке приостановки. Результат (возвращаемое значение,StopIteration
или другое исключение) такой же, как при итерации по возвращаемому значению__await__()
, описанной выше. Если исключение не было поймано в корутине, оно возвращается к вызывающей стороне.
-
coroutine.
close
()¶ Вызывает самоочистку и выход из программы. Если программа приостановлена, этот метод сначала делегирует метод
close()
итератора, который вызвал приостановку программы, если у него есть такой метод. Затем он поднимаетGeneratorExit
в точке приостановки, заставляя коридор немедленно очистить себя. Наконец, коридор помечается как завершивший выполнение, даже если он никогда не был запущен.Объекты Coroutine автоматически закрываются с помощью вышеуказанного процесса, когда они собираются быть уничтоженными.
3.4.3. Асинхронные итераторы¶
Асинхронный итератор* может вызывать асинхронный код в своем методе __anext__
.
Асинхронные итераторы можно использовать в операторе async for
.
-
object.
__aiter__
(self)¶ Должен возвращать объект асинхронного итератора.
-
object.
__anext__
(self)¶ Должен возвращать ожидание, приводящее к следующему значению итератора. Должна вызывать ошибку
StopAsyncIteration
, когда итерация завершается.
Пример асинхронного итерируемого объекта:
class Reader:
async def readline(self):
...
def __aiter__(self):
return self
async def __anext__(self):
val = await self.readline()
if val == b'':
raise StopAsyncIteration
return val
Добавлено в версии 3.5.
Изменено в версии 3.7: До Python 3.7 функция __aiter__()
могла возвращать awaitable, который разрешался в asynchronous iterator.
Начиная с Python 3.7, __aiter__()
должен возвращать объект асинхронного итератора. Возврат чего-либо другого приведет к ошибке TypeError
.
3.4.4. Асинхронные контекстные менеджеры¶
Асинхронный контекстный менеджер* - это контекстный менеджер, который способен приостанавливать выполнение в своих методах __aenter__
и __aexit__
.
Асинхронные менеджеры контекста можно использовать в операторе async with
.
-
object.
__aenter__
(self)¶ Семантически аналогичен
__enter__()
, с той лишь разницей, что он должен возвращать ожидаемое.
-
object.
__aexit__
(self, exc_type, exc_value, traceback)¶ Семантически аналогичен
__exit__()
, с той лишь разницей, что он должен возвращать ожидаемое.
Пример класса асинхронного менеджера контекста:
class AsyncContextManager:
async def __aenter__(self):
await log('entering context')
async def __aexit__(self, exc_type, exc, tb):
await log('exiting context')
Добавлено в версии 3.5.
Сноски
- 1
В некоторых случаях возможно изменить тип объекта при определенных контролируемых условиях. Обычно это не очень хорошая идея, так как при неправильном подходе это может привести к очень странному поведению.
- 2
Методы
__hash__()
,__iter__()
,__reversed__()
и__contains__()
имеют специальную обработку для этого; другие методы по-прежнему будут вызыватьTypeError
, но могут делать это, полагаясь на то, чтоNone
не является вызываемым.- 3
«Не поддерживает» здесь означает, что класс не имеет такого метода, или метод возвращает
NotImplemented
. Не устанавливайте метод вNone
, если вы хотите принудительно вернуть отраженный метод правого операнда - это приведет к обратному эффекту явного блокирования такого возврата.- 4
Для операндов одного типа предполагается, что если неотраженный метод - например,
__add__()
- не работает, то операция в целом не поддерживается, поэтому отраженный метод не вызывается.