We examine two objects: <type 'object'> and
<type 'type'>.
The names of the two primitive objects within
Python. Earlier | |
Exploring | |
Exploring |
Let's make use of our slate and draw what we've seen.
These two objects are primitive objects in Python. We might as well have introduced them one at a time but that would lead to the chicken and egg problem - which to introduce first? These two objects are interdependent - they cannot stand on their own since they are defined in terms of each other.
Continuing our Python experimentation:
Whoa! What happened here?
This is just Dashed Arrow Up Rule in action. Since | |
Applying both Dashed Arrow Up Rule and Dashed Arrow Down Rule, we can effectively reverse the direction of the dashed arrow. Yes, it is still consistent. |
If the above example proves too confusing, ignore it - it is not much use anyway.
Now for a new concept - type objects. Both the objects we introduced are type objects. So what do we mean by type objects? Type objects share the following traits:
They are used to represent abstract data types in programs. For instance, one (user defined) object called
Usermight represent all users in a system, another once calledintmight represent all integers.They can be subclassed. This means you can create a new object that is somewhat similar to exsiting type objects. The existing type objects become bases for the new one.
They can be instantiated. This means you can create a new object that is an instance of the existing type object. The existing type object becomes the
__class__for the new object.The type of any type object is
<type 'type'>.They are lovingly called types by some and classes by others.
Yes you read that right. Types and classes are really the same in
Python (disclaimer: this doesn't apply to old-style classes or pre-2.2
versions of Python. Back then types and classes had their differences
but that was a long time ago and they have since reconciled their
differences so let bygones be bygones, shall we?). No wonder
the type() function and
the __class__ attribute get you the same thing.
The term class was traditionally used to
refer to a class created by the class
statement. Built-in types (such as int
and string) are not usually referred to as classes,
but that's more of a convention thing and in reality types and classes
are exactly the same thing. In fact, I think this is important enough
to put in a rule:
Class is Type is Class
The term type is equivalent to the term class in all version of Python >= 2.3.
Types and (er.. for lack of a better word) non-types (ugh!) are both
objects but only types can have subcasses. Non-types are concrete
values so it does not make sense for another object be a subclass. Two
good examples of objects that are not types are the
integer 2 and the
string "hello". Hmm.. what does it mean to be a
subclass of 2?
Still confused about what is a type and what is not? Here's a handy rule for you:
Type Or Non-type Test Rule
If an object is an instance of <type 'type'>, then it is
a type. Otherwise, it is not a type.
Looking back, you can verify that this is true for all objects
we have come across, including <type 'type'> which is an instance of
itself.
To summarize:
<type 'object'>is an instance of<type 'type'>.<type 'object'>is a subclass of no object.<type 'type'>is an instance of itself.<type 'type'>is a subclass of<type 'object'>.There are only two kinds of objects in Python: to be unambiguous let's call these types and non-types. Non-types could be called instances, but that term could also refer to a type, since a type is always an instance of another type. Types could also be called classes, and I do call them classes from time to time.
Note that we are drawing arrows on our slate for only the
direct relationships, not the implied ones
(i.e. only if one object is another's __class__, or
in the other's __bases__). This make economic use of
the slate and our mental capacity.
<type 'object'>
>>> type
<type 'type'>
>>> type(object)
<type 'type'>
>>> object.__class__
<type 'type'>
>>> object.__bases__
()
>>> type.__class__
<type 'type'>
>>> type.__bases__
(<type 'object'>,)
