[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