Chapter 2. Bring In The Objects

The First Objects

We examine two objects: <type 'object'> and <type 'type'>.

Example 2.1. Examining <type 'object'> and <type 'type'>

>>> object 1
<type 'object'>
>>> type 2
<type 'type'> 
>>> type(object) 3
<type 'type'>
>>> object.__class__ 4
<type 'type'>
>>> object.__bases__ 5
()
>>> type.__class__ 6
<type 'type'>
>>> type.__bases__ 7
(<type 'object'>,)



1 2

The names of the two primitive objects within Python. Earlier type() was introduced as a way to find the type of an object (specifically, the __class__ attribute). In reality, it is both - an object itself, and a way to get the type of another object.

3 4 5

Exploring <type 'object'>: the type of <type 'object'> is <type 'type'>. We also use the __class__ attribute and verify it is the same as calling type().

6 7

Exploring <type 'type'>: interestingly, the type of <type 'type'> is itself! The __bases__ attribute points to <type 'object'>.

Let's make use of our slate and draw what we've seen.

Figure 2.1. Chicken and Egg

Chicken and Egg

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:

Example 2.2. There's more to <type 'object'> and <type 'type'>

>>> isinstance(object, object) 1
True
>>> isinstance(type, object) 2
True



1

Whoa! What happened here? This is just Dashed Arrow Up Rule in action. Since <type 'type'> is a subclass of <type 'object'>, instances of <type 'type'> are instances of <type 'object'> as well.

2

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 User might represent all users in a system, another once called int might 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:

  1. <type 'object'> is an instance of <type 'type'>.

  2. <type 'object'> is a subclass of no object.

  3. <type 'type'> is an instance of itself.

  4. <type 'type'> is a subclass of <type 'object'>.

  5. 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.