19

I'm a bit confused about types and classes in Python. For e.g. the following REPL conversation confuses me:

>>> 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__'
  1. Why is the type and class for inbuilt things (e.g. list here) the same but different for user classes/types?
  2. Isn't every class an instance of some other class (like Class in Java)? Why no __class__ for user defined classes?

Any explanation/further reading which can clarify this behaviour would be much appreciated. TIA.

sasuke
  • 6,589
  • 5
  • 36
  • 35

3 Answers3

16

You're encountering the different behavior for new style classes versus classic classes. For further reading read this: Python Data Model. Specifically read the section on classes and the difference between new style and classic classes.

Try typing the following into your REPL:

class A: pass
class B(object): pass

and you'll see that you get different results. Here you're dealing with the difference between new style and old style classes. Using Python 2.6.1 here's what I get:

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

which tells you that lists are new style classes and not old style classes. We can further play around with things using list as well:

> type(list)
<type "type">

same as our class B(object): pass result. And also

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

which is telling you about the instance of the object and not it's definition.

Zero Piraeus
  • 56,143
  • 27
  • 150
  • 160
wheaties
  • 35,646
  • 15
  • 94
  • 131
  • It seems that my wrong was with not using new typeclasses which ended up giving me weird results (surely for backward compatibility). The link looks interesting. Thanks. – sasuke Dec 18 '10 at 19:59
4

It's "Hystorical reasons". Or possible "Histerical". It's all fixed in 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'>
Lennart Regebro
  • 167,292
  • 41
  • 224
  • 251
  • That's nice to know. Didn't realize Python 3 had fixed the issue all together. I assume then, that all classes regardless of explicitly deriving from `object` derive from `object` then? – wheaties Dec 18 '10 at 20:04
3

In Python 3.0, user-defined class objects are instances of the object named type, which is itself a class. • In Python 2.6, new-style classes inherit from object, which is a subclass of type; • classic classes are instances of type and are not created from a class.

user2352151
  • 81
  • 1
  • 5