[Tutor] class questions

Steven D'Aprano steve at pearwood.info
Sun Jun 27 02:09:38 CEST 2010


On Sun, 27 Jun 2010 03:05:16 am Payal wrote:
> Thanks a lot for the quick answer. Still some doubts below.
>
> On Sat, Jun 26, 2010 at 11:07:17PM +1000, Steven D'Aprano wrote:
> > The old MRO (Method Resolution Order) is broken for classes using
> > multiple inheritance with a diamond shape inheritance diagram. Not
> > a little bit broken, but horribly, horribly broken.
> >
> > If you have something like this class hierarchy:
>
> [...]
>
> > (only with actual methods, of course) then inheritance with
> > old-style classes cannot work correctly in some circumstances.
> > Fortunately this
>
> Can you give any simple example where this simple mro will work
> incorrectly?

Probably not... it's quite complicated, which is why it's rare. I'll 
have a think about it and see what I can come up with.


> i read, 
> http://www.python.org/download/releases/2.3/mro/
> butdid not get where mro will fail (ofcourse if python implemented it
> corrrectly).

I think you have misunderstood, which is probably my fault. It's not 
that the implementation of the classic MRO was buggy, but that the MRO 
*itself* does not work as wanted. That's why the fix wasn't "just fix 
the code", but "change the MRO".


> > is rare for old-style classes. But for new-style classes, *all*
> > multiple inheritance is diamond-shaped, because all classes inherit
> > back to object at the top of the diagram:
>
> still not getting , how do the new style classes solve the problem
> (if there was any).

By changing the MRO, new-style classes avoid the problem completely. I 
know it's hard to understand without seeing an example, sorry.


> > Python doesn't have a special "abstract class" type, but it is easy
> > to make one with just two lines of boilerplate:
>
> [...]
>
> Sorry, I am not getting it. I get,
> NameError: global name 'Abstract' is not defined

Oops! That was my fault. I changed the name of the class from Abstract 
to AbstractThing but only changed it in one place. Oh, and I had 
another bug in it too. Here's the code corrected, and tested this time:

class AbstractThing(object):
    def __init__(self):
        # Next two lines are boilerplate.
        if type(self) is AbstractThing:
            raise TypeError("abstract class, you must subclass this")
        # init code for non-abstract Thing classes goes here

class MyThing(AbstractThing):
    pass

x = MyThing()  # works
y = AbstractThing()  # fails



> Was that a working code? (cos' I do not know what you mean by
> boilerplate)

"Boilerplate" means the sort of boring code that doesn't actually solve 
your problem, but just sets things up for the rest of your code to 
solve your problem. Boilerplate is usually bad because you have to 
repeat it over and over again, e.g. declarations in languages like 
Pascal, C or Java.  The amount of boilerplate sometimes exceeds the 
amount of code actually doing something!

If you have a class with twenty methods that all start like this:

def method(self, other):
    if other is None:
         other = something_else
    # more code here

you'll quickly get bored and frustrated writing the if clause. 
Especially when later on you realise that you mean something_different 
instead of something_else, and now you have to go back and change it in 
twenty places instead of one. *That's* boilerplate.



> > class DomainError(ValueError):
> >     """Used for mathematics domain errors."""
> >     pass
>
> Can we say that our own exception classes have only maybe a
> doc-string and pass, nothing more?

Technically speaking, if you have a doc string, you don't need the 
pass :)

This is a common design pattern. It is creating a new exception that is 
exactly the same as ValueError but with a different name. But that's 
not all you can do -- you can add as much, or as little, functionality 
to the exception subclass as you like.



-- 
Steven D'Aprano


More information about the Tutor mailing list