Типы и классы в 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 классы нового стиля наследуются от объекта, который является подклассом типа;
• классические классы являются экземплярами типа и не созданы из класса.