Trying to understand Python objects

Ben Finney bignose+hates-spam at benfinney.id.au
Tue Nov 21 20:15:04 EST 2006


"walterbyrd" <walterbyrd at iname.com> writes:

> Reading "Think Like a Computer Scientist" I am not sure I understand
> the way it describes the way objects work with Python.

Congratulations for taking the effort to figure it out, and for
thinking about the questions you want answered.

> 1) Can attributes can added just anywhere? I create an object called
> point, then I can add attributes any time, and at any place in the
> program?

Generally, yes. It's up to the programmer to do so in a way that's
readable and makes sense to later readers. There are conventions, of
course, and you should ask about anything specific that confuses you.

One convention that you seem to be unaware of is that assigning
attributes outside of the class's methods is unusual. This is only a
convention, though, and not enforced by the language; on the uncommon
occasions you need to add attributes to an instance outside that
class's methods, you're not prevented from doing it.

> 2) Are classes typically created like this:
>
> class Point:
>   pass

Typically, classes are created as a subclass of another class. The
top-level basic type in Python is 'object', so if your class doesn't
make sense deriving from anything else, derive from 'object'.

    class Point(object):
        pass

Defining a class with *no* superclass is not recommended. If you don't
yet understand the difference between the above style (called a
"new-style" class) and the style you presented, you should always
derive from a superclass ('object' or something more specific) until
you encounter a situation where that causes a problem.

> Then attributes are added at some other time?

No. Typically, the desired attributes are added either to the class
when it is defined, resulting in an attribute value that is shared by
all instances of that class::

    class Point(object):
        spam = 4

Or, the attributes are added to a specific instance (often in the
initialisation method) so that each instance has a separate attribute
with the same name::

    class Point(object):
        spam = 4
        def __init__(self):
            eggs = 2

> 3) What is with the __underscores__ ??

Another convention. Names of the form '__foo__' are a signal to the
reader that this name will be treated specially; often the internals
of Python syntax or some builtin type will look for those names when
performing behind-the-scenes magic.

For instance, the '__init__' attribute of a class is expected to be a
function, and that function is called by Python's instance creation
steps immediately after the creation of an instance. Thus, it is used
to "initialise" the newly-created instance of the class, doing things
specific to that instance.

> 4) Are parameters passed to an class definition?
>
> class Whatever(params):
>    pass

The parameters of the class definition are the super-classes from
which this class should inherit its attributes. They don't correspond
with the parameters to the class constructor.

When you create a new instance of a class, its constructor is called
to create the new instance, and then the initialiser is called, to
perform post-creation steps on the new instance. This all occurs in
one step, as far as the code that called the constructor is concerned.

Unlike in many other languages, you will rarely need to define a
constructor ('__new__') for your Python classes. It's far more common
to let the default constructor create the object, and have any
initialisation steps on the newly-created instance performed in the
class '__init__' method.

The __init__ method gets called by Python's internals (hence the
"special" name with underscores) immediately after the creation of the
instance. It is called with parameters consisting of the newly-created
instance object, followed by all the parameters that were passed to
the constructor.

    origin = Point(0, 0)

This will call the constructor of the Point class, which will create a
new instance; then, the __init__ method of the Point class will be
called with the parameters (<new Point instance>, 0, 0). This means
the function has access to the specific instance, and can modify it
accordingly.

The convention is to use 'self' as the name to refer to the first
parameter to instance methods, so that the instance object is referred
to by the parameter name 'self' in that method.

    class Point(object):
        spam = 4
        def __init__(self, x_coord, y_coord):
            if x_coord < 0:
                x_coord = 0
            if y_coord < 0:
                y_coord = 0
            self.x = x_coord
            self.y = y_coord

This initialisation method does a bit of value fudging, then assigns
values to attributes of the instance, named 'self' in the context of
the method.

After the constructor and the __init__ method have finished, the
program continues at the point where the constructor was called. Thus,
the attributes assigned to the instance are immediately available::

    origin = Point(0, 0)
    print origin.x

-- 
 \      "Anyone who believes exponential growth can go on forever in a |
  `\     finite world is either a madman or an economist."  -- Kenneth |
_o__)                                                         Boulding |
Ben Finney




More information about the Python-list mailing list