Типы и классы в Python

Я немного смущен о типах и классах в Python. Напр. следующий диалог REPL меня смущает:

>>> class A: pass
... 
>>> a = A()
>>> type(a)
<type 'instance'>
>>> a.__class__
<class __main__.A at 0xb770756c>
>>> type([])
<type 'list'>
>>> [].__class__
<type 'list'>
>>> type(list)
<type 'type'>
>>> list.__class__
<type 'type'>
>>> type(A)
<type 'classobj'>
>>> A.__class__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: class A has no attribute '__class__'
  • Почему тип и класс встроенных объектов (например, список здесь) одинаковые, но разные для пользовательских классов/типов?
  • Разве не каждый класс является экземпляром какого-либо другого класса (например, класса в Java)? Почему нет __class__ для пользовательских классов?

Любое объяснение/дальнейшее чтение, которое может прояснить это поведение, будет высоко оценено. ТИА.

Ответы

Ответ 1

Вы сталкиваетесь с различным поведением для классов нового стиля и классических классов. Для дальнейшего чтения читайте следующее: Модель данных Python. В частности, прочитайте раздел о классах и разницу между новым стилем и классическими классами.

Попробуйте ввести в свой REPL следующее:

class A: pass
class B(object): pass

и вы увидите, что у вас разные результаты. Здесь вы имеете дело с разницей между новым стилем и классами старого стиля. Используя Python 2.6.1 здесь, что я получаю:

> type(A)
<type "classobj">
> type(B)
<type "type">

который сообщает вам, что списки - это новые классы стиля, а не классы старого стиля. Мы также можем поиграть с вещами, используя list:

> type(list)
<type "type">

аналогично нашему результату class B(object): pass. А также

> c = []
> type(c)
<type "list">

который сообщает вам об экземпляре объекта, а не о его определении.

Ответ 2

Это "Исторические причины". Или возможно "Histerical". Все это исправлено в Python 3:

>>> class A: pass
... 
>>> a = A()
>>> type(a)
<class '__main__.A'>
>>> a.__class__
<class '__main__.A'>
>>> type([])
<class 'list'>
>>> [].__class__
<class 'list'>
>>> type(list)
<class 'type'>
>>> list.__class__
<class 'type'>
>>> type(A)
<class 'type'>
>>> A.__class__
<class 'type'>
>>> class B(object): pass
... 
>>> type(B)
<class 'type'>
>>> b = B()
>>> type(b)
<class '__main__.B'>

Ответ 3

В Python 3.0 пользовательские объекты класса являются экземплярами объекта с именем type, который сам по себе является классом. • В Python 2.6 классы нового стиля наследуются от объекта, который является подклассом типа; • классические классы являются экземплярами типа и не созданы из класса.