13.5. Instances

Whereas a class is a data structure definition type, an instance is a declaration of a variable of that type. In other words, instances are classes brought to life. Once a blueprint is provided, the next step to bring them to fruition. Instances are the objects which are used primarily during execution, and all instances are of type “instance.”

13.5.1. Instantiation: Creating Instances by Invoking Class Object

Most other OO languages provide a new keyword with which to create an instance of a class. Python's approach is much simpler. Once a class has been defined, creating an instance is no more difficult that calling a function—literally. Instantiation is realized with use of the function operator, as in the following example:

>>> class MyClass:              # define class
…        pass
>>> myInstance = MyClass()      # instantiate class
>>> type(MyClass)               # class is of class type
<type 'class'>
>>> type(myInstance)            # instance is of
instance type
<type 'instance'>

CORE NOTE: Classes and instances are generic types

The use of the term “type” in Python may perhaps differ from the general connotation of an instance being of the type of class it was created from. In Chapter 4, we introduced all Python objects as data entities with three characteristics: an ID, a type, and a value. An object's type dictates the behavioral properties of such objects in the Python system, and these types are a subset of all types which Python supports.

User-defined “types” such as classes are categorized in the same manner. Classes share the same type, but have different IDs and values (their class definitions). The fact that all classes are defined with the same syntax, that they can be instantiated, and that all have the same core properties leads to the conclusion that they have common characteristics which allow them to fall under the same category. Classes are unique objects which differ only in definition, hence they are all the same “type” in Python. Class instances follow the same argument.

Do not let Python's nomenclature fool you; instances are most assuredly related to the class they were instantiated from and would not have any other relationship to other instances (unless they were of a subclass or base class).

To avoid confusion, keep the following in mind: When you are defining a class, you are not creating a new type. You are just defining a unique class type, but it is still a class. When you instantiate classes, the resulting object is always an instance. Even though instances may be instantiated from different classes, they are still (generically) class instances.


As you can see, creating instance myInstance of class MyClass consists of “calling” the class: MyClass(). The return object of the call is an instance object. We also verified the data types of MyClass and myInstance using type(): MyClass is a class object and myInstance is an instance object. To take this even further, we tell you now that all classes are of the same type (type class), and all instances are of the same type (type instance). (You can verify this using the type() built-in function.)

13.5.2. __init__() Constructor Method

When the class is invoked, the first step in the instantiation process is to create the instance object. Once the object is available, a check to see if a constructor has been implemented is called. By default, no special actions are enacted on the instance without the overriding of the constructor, the special method __init__(). Any special action desired requires the programmer to implement __init__(), overriding its default behavior. If __init__() has not been implemented, the object is then returned and the instantiation process is complete.

However, if __init__() has been implemented, then that special method is invoked and the instance object passed in as the first argument (self), just like a standard method call. Any arguments passed to the class invocation call are passed on to __init__(). You can practically envision the call to create the class as a call to the constructor.

__init__() is one of many special methods which can be defined for classes. Some of these special methods are predefined with inaction as their default behavior (such as __init__()) and must be overridden for customization while others should be implemented on an as-needed basis. We will go over special methods in Section 13.13 later on in this chapter.

13.5.3. __del__() Destructor Method

Likewise, there is an equivalent destructor special method called __del__(). However, due to the way Python manages garbage collection of objects (by reference counting), this function is not executed until all references to an instance object have been removed. Destructors in Python are methods which provide special processing before instances are deallocated and are not commonly implemented since instances are seldom deallocated explicitly.

CORE NOTE: Keeping Track of Instances

Python does not provide any internal mechanism to track how many instances of a class have been created nor to keep tabs on what they are. You can explicitly add some code to the class definition and perhaps __init__() and __del__() if such functionality is desired. The best way is to keep track of the number of instances using a static member. It would be dangerous to keep track of instance objects by saving references to them, because you must manage these references properly or else your instances will never be deallocated (because of your extra reference to them)! An example follows:

								class myClass:
   count = 0                 # use static data for count
   def __init__(self):       # constructor, incr. count
          myClass.count = myClass.count + 1
   def __del__(self):        # destructor, decr. count
          myClass.count = myClass.count - 1
          assert myClass > 0  # cannot have < 0 instances
   def howMany(self):        # return count
          return myClass.count
>>> a = myClass()
>>> b = myClass()
>>> b.howMany()
2
>>> a.howMany()
2
>>> del b
>>> a.howMany()
1
>>> del a
>>> myClass.count
0


In the following example, we create (and override) both the __init__() and __del__() constructor and destructor functions, respectively, then instantiate the class and assign more aliases to the same object. The id() built-in function is then used to confirm that all three aliases reference the same object. The final step is to remove all the aliases by using the del statement and discovering when and how many times the destructor is called.

>>> class C:                   # class declaration
        def __init__(self):    # constructor
            print 'initialized'
        def __del__(self):     # destructor
            print 'deleted'

>>> c1 = C()                   # instantiation
initialized
>>> c2 = c1                    # create additional alias
>>> c3 = c1                    # create a third alias
>>> id(c1), id(c2), id(c3)     # all refer to same object
(11938912, 11938912, 11938912)
>>> del c1                     # remove one reference
>>> del c2                     # remove another reference
>>> del c3                     # remove final reference
deleted                        # destructor finally invoked

Notice how, in the above example, the destructor was not called until all references to the instance of class C were removed, i.e., when the reference count has decreased to zero. If for some reason your __del__() method is not being called when you are expecting it to be invoked, this means that somehow your instance object's reference count is not zero, and there may be some other reference to it that you are not aware of that is keeping your object around.

Also note that the destructor is called exactly once, the first time the reference count goes to zero and the object deallocated. This makes sense because any object in the system is allocated and deallocated only once.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset