Статьи

Глоссарий объектов, типов, классов и экземпляров Python

Когда я писал статью о внутренностях вызываемых в Python , мне пришло в голову, что некоторые вещи в Python имеют более одного имени. В то же время некоторые имена иногда используются для обозначения более чем одной сущности, и какая из них подразумевается, следует понимать из контекста. Поэтому я считаю хорошей идеей собрать эту номенклатуру в одном месте ради моих будущих работ. Таким образом, я просто буду указывать здесь каждый раз, когда буду обсуждать эти темы, вместо того, чтобы объяснять их снова и снова.

В частности, я хочу определить, что я имею в виду под типами , объектами , классами и экземплярами . Обратите внимание, что это относится к Python 3.x, но в основном применимо и к 2.x [1] .

Объекты

Проще всего начать с объектов . Ссылка на модель данных Python имеет довольно хорошее определение:

Объекты — это абстракция Python для данных. Все данные в программе Python представлены объектами или отношениями между объектами. (В некотором смысле и в соответствии с моделью фон Неймана «компьютер с хранимой программой» код также представлен объектами.)

Каждый объект имеет идентичность, тип и значение.

Итак, все в Python является объектом. Списки являются объектами. 42 это объект. Модули являются объектами. Функции являются объектами. Байт-код Python также хранится в объекте. Все они имеют типы и уникальные идентификаторы:

>>> def foo(): pass
...
>>> type(foo), id(foo)
(<class 'function'>, 38110760)
>>> type(foo.__code__), id(foo.__code__)
(<class 'code'>, 38111680)

Эта модель «все является объектом» поддерживается реализацией CPython. Действительно, если вы заглянете в код CPython, вы заметите, что с каждой сущностью, упомянутой выше, можно манипулировать с помощью указателя на базовую структуру PyObject.

Типы

Ссылка на модель данных полезна и здесь:

[…] Тип объекта определяет операции, которые объект поддерживает (например, «имеет ли он длину?»), А также определяет возможные значения для объектов этого типа.

Итак, каждый объект в Python имеет тип. Его тип можно узнать, вызвав встроенную функцию type [2] . Тип также является объектом, поэтому у него есть собственный тип, который называется типом. Этот последний факт может быть не очень интересным или полезным, когда вы просто пишете код на Python, но он чрезвычайно важен, если вы хотите понять внутренности CPython:

>>> type(42)
<class 'int'>
>>> type(type(42))
<class 'type'>
>>> type(type(type(42)))
<class 'type'>

Да, это черепахи все время вниз.

Классы

В былые времена существовала разница между пользовательскими классами и встроенными типами. Но начиная с версии 2.2 , если вы используете классы «нового стиля» (классы, которые наследуются от объекта в 2.x и используются по умолчанию в 3.x), реальной разницы нет. По сути, класс — это механизм, который Python дает нам для создания новых пользовательских типов из кода Python.

>>> class Joe: pass
...
>>> j = Joe()
>>> type(j)
<class '__main__.Joe'>

Используя механизм классов, мы создали Joe — пользовательский тип. J является экземпляром класса Джо. Другими словами, это объект, и его тип — Джо.

Как и любой другой тип, Джо сам является объектом, и у него тоже есть тип. Этот тип является типом:

>>> type(type(j))
<class 'type'>

Термины «класс» и «тип» являются примером двух имен, относящихся к одному и тому же понятию. Чтобы избежать этой путаницы, я всегда буду пытаться сказать «тип», когда имею в виду тип, и «пользовательский класс» (или «пользовательский тип»), когда ссылаюсь на новый тип, созданный с использованием конструкции класса. Обратите внимание, что когда мы создаем новые типы с использованием C API в CPython, «класс» не упоминается — мы создаем новый «тип», а не новый «класс».

Инстансы

В отличие от неоднозначности между «классом» и «типом», «экземпляр» является синонимом «объекта». Думайте об этом так: объекты являются экземплярами типов . Таким образом, «42 является экземпляром типа int» эквивалентно «42 является объектом int». Я обычно использую «экземпляр» и «объект» взаимозаменяемо. В некоторых случаях, когда я хочу специально ссылаться на объекты как на артефакты реализации CPython, я попытаюсь использовать «экземпляр» для ссылки на фактические экземпляры классов. Еще одно место, где термин «экземпляр» явно используется Python, — это встроенные модули, такие как isinstance и специальный атрибут __instancecheck__.

Вывод

Как мы уже видели, в номенклатуре Python есть две пары примерно синонимичных терминов. Типы и классы являются взаимозаменяемыми понятиями. Я предпочитаю говорить «тип» везде, где это возможно, оставляя термин «класс» для пользовательских типов, созданных с помощью конструкции «класс». ИМХО «тип» — лучший термин, и Python не был бы хуже, если бы концепция «класса» была полностью уничтожена.

Точно так же объекты и экземпляры — это термины, которые означают одно и то же, но, возможно, с немного разных точек зрения. Иногда удобнее использовать «экземпляр» (т. Е. Когда речь идет о конкретных объектах, являющихся экземплярами определенных типов — как в «j это экземпляр Джо»), а иногда лучше использовать «объект» (т. Е. При обсуждении кишок). реализации CPython).

Я искренне надеюсь, что этот пост более полезен, чем запутан! Для меня это помощь, которая служит простым глоссарием, когда мое использование этих терминов в какой-то статье может быть неясным или двусмысленным.

http://eli.thegreenplace.net/wp-content/uploads/hline.jpg

[1] Пока вы забудете о существовании классических классов 2.x и примете это как факт, что все пользовательские классы наследуются от объекта.
[2] Альтернативой является атрибут __class__.