OO-programming question

Alex Martelli aleaxit at yahoo.com
Sun Sep 3 21:39:16 CEST 2000


"Ing. Roman Fischer" <Roman.Fischer at teleweb.at> wrote in message
news:B5D85A24.7654%Roman.Fischer at teleweb.at...
> Reading "Learning Python" I have problems of understanding the advantages
of
> the concept of object-oriented programming in Python:
>
> 1. When I understand it wright I can add/delete items to classes AND to
> object AFTER their definition. What is the advantage of this concept? I

Same as any other dynamic aspect -- you can easily adapt your
program's actual structure to the problem it's handling, on the fly.

> think it destroys the possibillity to know what a  class or object
consists
> of.

No, you can easily use what in Java is called 'reflection' if at some
point in your program you need to determine what attributes a
class or instance has at that time.  See the hasattr function.

More to the point, you only use dynamic features when they're
a *plus*: when they HELP you program more effectively.  Nothing
_forces_ you to use them when there's no need.  "Do the simplest
thing that could possibly work"...


> 2. In Java and Visual Basic there is the concept of interfaces (a
definition
> of what a class must have included when implementing the interface). Is
> there anything like that in Python?

The concept of 'signature' -- a set of methods that an instance must
support to be usefully used in a certain context.  But it's dynamic and
depends only on what it's actually *used*.

E.g., a builtin file-object supports a .write() method taking one
argument; it also supports .writelines() that takes a sequence
and is equivalent to calling .write() on each item in turn, and
others.  But: to make some instance-object that is usable in an
interchangeable way in place of a file-object, you to not usually
have to implement both methods; in most cases, the client code
(that you can, if you wish, pass your ersatz file-object to) will
undertake to only use the .write() method.  The required signature
is therefore in this case extremely simple.


> 3. In Java there is the concept of abstract classes (a class that have a
lot
> of definitions (e.g. methods) but not all is really implemented, so a
> derived class has to implement). Is there anything like that in Python?

Python is not much about 'must', 'has to', and so on.  It's more about
*enabling* you to do things, than about *forcing* you to:-).

You can, if you wish, have a class that will implement methods that
raise exceptions when called; this will 'force' subclasses to override
those methods *IF* they're actually called.  It's not a common idiom
in Python, but you can make use of it, if you wish.


> 4. How do I find out to which class(es) an object belongs to?

The __class__ attribute, that every instance has, tells you the (one
and only) class to which that instance belongs.  The class object,
which you thus obtain, has a __bases__ attribute that lists all of
its base-classes (and you can recurse upwards to get it all; in case
it matters, Python's search for attributes is depth-first left-first).

For typical uses, see the isinstance and issubclass builtin functions;
those do the tree-search for you, for the specific cases of checking
whether an instance does belong to a certain given class, etc.

But here, for example, is a way to get an _exhaustive_ list of
an instance's class-and-bases:

def allbases(aclass, baselist=[]):
    baselist.append(aclass)
    bases=aclass.__bases__
    for base in bases:
        allbases(base, baselist)
    return baselist

def allclasses(aninstance):
    return allbases(aninstance.__class__)

This, however, may return a classlist with duplicates due to multiple
repeated inheritance.  To avoid duplicates, just add one line to
allbases...:

def allbases(aclass, baselist=[]):
    if not aclass in baselist:
        baselist.append(aclass)
        bases=aclass.__bases__
        for base in bases:
            allbases(base, baselist)
    return baselist

This has the useful property of returning classes *in the order
in which Python will look them up* when you look for an
attribute (depth-first, left-first).  So, you can use it as a
building block for other introspection, such as finding out
"where" an attribute will be found (if it's found at all...:)

def whereattr(aninstance, attrname):
    if aninstance.__dict__.has_key(attrname):
        return aninstance
    for base in allbases(aninstance):
        if base.__dict__.has_key(attrname):
            return base
    return None

You can omit the final return None, as that is what Python
does by default if it "runs off the end" of a function, but
inserting it explicitly may be considered more readable
by some.

Note that this is all good clean fun, but it's *NOT* the
stuff you need for 99% of your programming tasks.  It's
very rare indeed that you *need* to use reflection --
rarer in Python than in Java, even.  It's handy for that
maybe-1%-of-cases, but that's all.

Mostly, when your function/object is handed an unknown
object, it will just use it according to the signature it has
documented it will use; maybe with a try/except around
it, if you've decided your 'contract' includes not letting
certain exceptions propagate (but, most often, exceptions
related to being given incorrect objects are best left to
propagate back to the caller...).


> 5. What is the advantage of including "self" into the paramters of a
method?

Explicitness.  "Explicit is better than implicit" is one of Python's
mantras.  It's one of the FAQ's of C++ "how come I can't pass
the address of my function int foo(int) to this library that requires
the address of just such a function" -- coming from the fact that
the questioner does not realize the "function" has a hidden,
implicit, 'magic' parameter of 'self' at the first position.  Stating
it means the function's signature is exactly the one you write:
what you see is what you get -- no black magic, no hidden
surprises.

Python specializes in not springing surprises at you: that's part
of what makes it so productive to use.  It sets simple rules and
follows them thoroughly; so you quickly learn what to expect,
and following your expectations tends to be a good guide to
language areas you haven't deeply explored yet.  Explicitness
is, in a sense, part of the no-surprises policy.


Alex






More information about the Python-list mailing list