Random remarks

[These should perhaps be placed more carefully...]

Data attributes override method attributes with the same name; to avoid accidental name conflicts, which may cause hard-to-find bugs in large programs, it is wise to use some kind of convention that minimizes the chance of conflicts, e.g., capitalize method names, prefix data attribute names with a small unique string (perhaps just an underscore), or use verbs for methods and nouns for data attributes.

Data attributes may be referenced by methods as well as by ordinary users (``clients'') of an object. In other words, classes are not usable to implement pure abstract data types. In fact, nothing in Python makes it possible to enforce data hiding — it is all based upon convention. (On the other hand, the Python implementation, written in C, can completely hide implementation details and control access to an object if necessary; this can be used by extensions to Python written in C.)

Clients should use data attributes with care — clients may mess up invariants maintained by the methods by stamping on their data attributes. Note that clients may add data attributes of their own to an instance object without affecting the validity of the methods, as long as name conflicts are avoided — again, a naming convention can save a lot of headaches here.

There is no shorthand for referencing data attributes (or other methods!) from within methods. I find that this actually increases the readability of methods: there is no chance of confusing local variables and instance variables when glancing through a method.

Conventionally, the first argument of methods is often called self. This is nothing more than a convention: the name self has absolutely no special meaning to Python. (Note, however, that by not following the convention your code may be less readable by other Python programmers, and it is also conceivable that a class browser program be written which relies upon such a convention.)

Any function object that is a class attribute defines a method for instances of that class. It is not necessary that the function definition is textually enclosed in the class definition: assigning a function object to a local variable in the class is also ok. For example:

        # Function defined outside the class
        def f1(self, x, y):
                return min(x, x+y)

        class C:
                f = f1
                def g(self):
                        return 'hello world'
                h = g

Now f, g and h are all attributes of class C that refer to function objects, and consequently they are all methods of instances of Ch being exactly equivalent to g. Note that this practice usually only serves to confuse the reader of a program.

Methods may call other methods by using method attributes of the self argument, e.g.:

        class Bag:
                def empty(self):
                        self.data = []
                def add(self, x):
                        self.data.append(x)
                def addtwice(self, x):
                        self.add(x)
                        self.add(x)

The instantiation operation (``calling'' a class object) creates an empty object. Many classes like to create objects in a known initial state. In early versions of Python, there was no special syntax to enforce this (see below), but a convention was widely used: add a method named init to the class, which initializes the instance (by assigning to some important data attributes) and returns the instance itself. For example, class Bag above could have the following method:

                def init(self):
                        self.empty()
                        return self

The client can then create and initialize an instance in one statement, as follows:

        x = Bag().init()

In later versions of Python, a special method named __init__ may be defined instead:

                def __init__(self):
                        self.empty()

When a class defines an __init__ method, class instantiation automatically invokes __init__ for the newly-created class instance. So in the Bag example, a new and initialized instance can be obtained by:

        x = Bag()

Of course, the __init__ method may have arguments for greater flexibility. In that case, arguments given to the class instantiation operator are passed on to __init__. For example,

>>> class Complex:
...     def __init__(self, realpart, imagpart):
...         self.r = realpart
...         self.i = imagpart
... 
>>> x = Complex(3.0,-4.5)
>>> x.r, x.i
(3.0, -4.5)
>>>
Methods may reference global names in the same way as ordinary functions. The global scope associated with a method is the module containing the class definition. (The class itself is never used as a global scope!) While one rarely encounters a good reason for using global data in a method, there are many legitimate uses of the global scope: for one thing, functions and modules imported into the global scope can be used by methods, as well as functions and classes defined in it. Usually, the class containing the method is itself defined in this global scope, and in the next section we'll find some good reasons why a method would want to reference its own class!