Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Abstract class

4 views
Skip to first unread message

Mr.SpOOn

unread,
Sep 14, 2008, 12:03:23 PM9/14/08
to pytho...@python.org
Hi,
I'm going to work on a project to represent some musical theory in
Python, in an object oriented way.

I have to manage many elements of music such as notes, intervals,
scales, chords and so on. All these elements share properties and
behavior, so what I want to do is an abstract class "Note" and other
subclasses, for example "NaturalNote", "FlatNote", "SharpNote" etc.

The idea is not original, I read it in some papers where they talk
about an implementation in smalltalk.

I want to use Python (of course) and I'd like to know what is the
practice in such a case. I mean, in python there aren't abstract
classes, but I read about some way to emulate the same behavior.

What do you suggest me?

Thanks,
Carlo

Larry Bates

unread,
Sep 14, 2008, 12:49:08 PM9/14/08
to

I think the issue is one of terminology not features. Note would be a base
class and it can have attributes (properties) and behavior (methods).
NaturalNote, FlatNote, SharpNote would inherit from Note.

-Larry

Bruno Desthuilliers

unread,
Sep 14, 2008, 11:33:20 AM9/14/08
to
Mr.SpOOn a écrit :

Conceptually, an abstract class is a class that is not intented to be
instanciated directly but used as a parent class. The simplest way to
get such behaviour is to just write your base class and avoid
instanciating it.

Roy Smith

unread,
Sep 14, 2008, 1:56:44 PM9/14/08
to
In article <mailman.1008.1221408...@python.org>,
Mr.SpOOn <mr.sp...@gmail.com> wrote:

> I have to manage many elements of music such as notes, intervals,
> scales, chords and so on. All these elements share properties and
> behavior, so what I want to do is an abstract class "Note" and other
> subclasses, for example "NaturalNote", "FlatNote", "SharpNote" etc.

What properties or behaviors does SharpNote have which NaturalNote doesn't?
Unless there is some new behavior, you don't need subclasses.

Are you also going to have DoubleSharpNote and DoubleFlatNote?

Consider the following code:

note1 = SharpNote("E4")
note2 = NaturalNote("F4")
if note1 == note2:
print "the same note"
else
print "different notes"

what should it print?

Christian Heimes

unread,
Sep 14, 2008, 2:19:17 PM9/14/08
to pytho...@python.org
Roy Smith wrote:
>Are you also going to have DoubleSharpNote and DoubleFlatNote?
>
> Consider the following code:
>
> note1 = SharpNote("E4")
> note2 = NaturalNote("F4")
> if note1 == note2:
> print "the same note"
> else
> print "different notes"
>
> what should it print?

Hehe, tricky question.

The answer depends on the music instrument and tuning. On a piano E# and
F are on the same key but other instruments (e.g. a violin) treat E# and
F as different notes. The enharmonic equivalent E# == F is only valid
for some instruments and tunes - noticeable for modern tunes like equal
temperament.

Christian

Mr.SpOOn

unread,
Sep 14, 2008, 2:55:02 PM9/14/08
to pytho...@python.org
Gary Harron:
>I believe you are mixing up class *inheritance* and *abstract* classes.

>Class inheritance (with Python has has for years) is how one class inherits >behavior/properties/attributes from another class. The class being inherited from is >called the base class. This is probably what you want.

Well, I know the difference between an abstract class and an inherited
one. The idea was to create a main class Note, with abstract methods,
and implement these methods in the other classes.

On Sun, Sep 14, 2008 at 7:56 PM, Roy Smith <r...@panix.com> wrote:
> What properties or behaviors does SharpNote have which NaturalNote doesn't?
> Unless there is some new behavior, you don't need subclasses.

Well, from a SharpNote I can obtain the relative NaturalNote. So if I
have a C# I can call

natural('C#') and get 'C'

While in the class NaturalNote I don't need such a method, but I need
two methods to get the sharped and flatted version

> Are you also going to have DoubleSharpNote and DoubleFlatNote?

Yes, that's an option.

> Consider the following code:
>
> note1 = SharpNote("E4")
> note2 = NaturalNote("F4")
> if note1 == note2:
> print "the same note"
> else
> print "different notes"
>
> what should it print?

Well, that's not so simple. The idea is that I use a notation (A, B,
C, D...) and an integer (a distance expressed in semitones) to
identify a note.

Anyway, I think I need an abstract class. Or not?

Gary Herron

unread,
Sep 14, 2008, 3:15:04 PM9/14/08
to pytho...@python.org
Mr.SpOOn wrote:
> Gary Harron:
>
>> I believe you are mixing up class *inheritance* and *abstract* classes.
>>
>
>
>> Class inheritance (with Python has has for years) is how one class inherits >behavior/properties/attributes from another class. The class being inherited from is >called the base class. This is probably what you want.
>>
>
> Well, I know the difference between an abstract class and an inherited
> one. The idea was to create a main class Note, with abstract methods,
> and implement these methods in the other classes.
>
> On Sun, Sep 14, 2008 at 7:56 PM, Roy Smith <r...@panix.com> wrote:
>
>> What properties or behaviors does SharpNote have which NaturalNote doesn't?
>> Unless there is some new behavior, you don't need subclasses.
>>
>
> Well, from a SharpNote I can obtain the relative NaturalNote. So if I
> have a C# I can call
>
> natural('C#') and get 'C'
>
> While in the class NaturalNote I don't need such a method, but I need
> two methods to get the sharped and flatted version
>
>
>> Are you also going to have DoubleSharpNote and DoubleFlatNote?
>>
>
> Yes, that's an option.
>
>
>> Consider the following code:
>>
>> note1 = SharpNote("E4")
>> note2 = NaturalNote("F4")
>> if note1 == note2:
>> print "the same note"
>> else
>> print "different notes"
>>
>> what should it print?
>>
>
> Well, that's not so simple. The idea is that I use a notation (A, B,
> C, D...) and an integer (a distance expressed in semitones) to
> identify a note.
>
> Anyway, I think I need an abstract class. Or not?
>

No! Definitely not! You need inheritance of a class from a base
class.

Implement your base class with whatever shared methods you want.
Implement your derived class with methods (new, inherited or
reimplemented) as you like.
(If you wish to consider the base class "abstract", just agree with
yourself to not instantiate it.)

Please forget about Abstract Base Classes. They have nothing to do with
what you want, and are a *HUGE* overkill for your application. They
are not (yet) even part of standard Python, and are used primarily for a
class implementor to guarantee to a user of a class that it provides a
specific interface.

Gary Herron

> --
> http://mail.python.org/mailman/listinfo/python-list
>

Mr.SpOOn

unread,
Sep 14, 2008, 3:19:06 PM9/14/08
to pytho...@python.org
On Sun, Sep 14, 2008 at 9:15 PM, Gary Herron <ghe...@islandtraining.com> wrote:
> Please forget about Abstract Base Classes. They have nothing to do with
> what you want, and are a *HUGE* overkill for your application. They are
> not (yet) even part of standard Python, and are used primarily for a class
> implementor to guarantee to a user of a class that it provides a specific
> interface.

Ok :D
I started to think to abstract classes just because in the paper it
uses an abstract class in SmallTalk.

Anyway, thanks.

Aaron "Castironpi" Brady

unread,
Sep 14, 2008, 3:21:54 PM9/14/08
to

Just brainstorming with you. You can support operations on the
objects: note minus note = interval, note plus interval = note, and so
on. (WARNING! Spoilers. Untested.)

note1 = NaturalNote("G")
note2 = NaturalNote("C")
interval= note1- note2
print interval
: <MajorInterval '5th'>

note1 = SharpNote("G")
note2 = NaturalNote("C")
interval= note1- note2
print interval
: <MinorInterval '6th'>

WholeStep= MajorInterval( 2 )
print WholeStep
: <MajorInterval '2nd'>
note1 = NaturalNote("C")
print note1- WholeStep
: <FlatNote("B")>

However, from what I understand (brass player), there are some cases
in which you'll want that to be:

print note1- WholeStep
: <SharpNote("A")>

What do you want to determine that? What about a KeyOf class?

key= KeyOf( NaturalNote( "F" ) )
#'key' has special subclasses
note1 = key.NaturalNote("C")
print note1- WholeStep
: <FlatNote("B")>

key= KeyOf( SharpNote( "G" ) )
note1 = key.NaturalNote("C")
print note1- WholeStep
: <SharpNote("A")>

Further, perhaps you want a 'WrittenNote' class which refers to the
key signature it's written in:

key= KeyOf( NaturalNote( "F" ) )
note1 = key.WrittenNote("B")
print note1
: <FlatNote("B")>

I do not immediately see how to represent clefs and staves: whether
you'll need them at all, or whether they're just writing/rendering
techniques.

As for scales and chords, are there any special methods you want on
them, or would a tuple of Note instances suffice?

triad= ( NaturalNote( "C" ), NaturalNote( "E" ), NaturalNote( "G" ) )

One special method might be:

triad= Triad( NaturalNote( "C" ), NaturalNote( "E" ),
NaturalNote( "G" ) )
print triad
: <C-Major triad>
triad= Triad( NaturalNote( "E" ), NaturalNote( "G" ),
NaturalNote( "C" ) )
print triad
: <C-Major triad 1st inversion>

I forgot about octaves, which can complicate the constructors.

octave= Octave( 4 ) #middle C
triad= Triad( octave.NaturalNote( "E" ), octave.NaturalNote( "G" ),
octave.up.NaturalNote( "C" ) )
print triad
: <C-Major triad 1st inversion>

Or:

octave= Octave( 4 )
triad= Triad( NaturalNote( "E", octave ), NaturalNote( "G", octave ),
NaturalNote( "C", octave.up ) )
print triad
: <C-Major triad 1st inversion>

And abbreviate the name for the interval.

octaveint= MajorInterval( 8 )

Abstract scales can be a tuple of intervals, where concrete scales are
a tuple of notes.

majorscale= ( Tonic, WholeStep, WholeStep, HalfStep,
WholeStep, WholeStep, WholeStep, HalfStep )

majorCscale= [ NaturalNote( "C" )+ x for x in majorscale ]
majorDscale= [ NaturalNote( "D" )+ x for x in majorscale ]

To get a little more creative, you could just denote sharps and flats
with a parameter:

note1 = Note("G", sharp)
#Or: note1 = Note("G", Note.sharp)
note2 = Note("C")
interval= note1- note2
print interval
: <MinorInterval '6th'>

It would just take some 'parameter magic' to interpret them right when
paired with octaves:

octave= Octave( 4 ) #middle C
note1= Note( "C", sharp, octave )
note2= Note( "C", octave )
note3= Note( "C", octave, sharp )
note4= Note( "C", sharp )

That part just takes a little untwisting. (Untested.)

class Note:
defaultoctave= 4
def __init__( self, *args ):
octave= Octave( self.defaultoctave )
accidental= Natural( )
for arg in args:
if issubclass( arg, Accidental ):
accidental= arg
elif issubclass( arg, Octave ):
octave= arg
elif type( arg ) is str:
name= arg

Or use keywords to specify.

octave= Octave( 4 ) #middle C
note1= Note( "C", sharp, octave )
note2= Note( "C", octave= octave )
note3= Note( "C", octave= octave, accidental= sharp )
note4= Note( "C", sharp )

class Note:
defaultoctave= 4
def __init__( self, name, octave= None, accidental= Natural( ) ):
if octave is None:
octave= self.defaultoctave

It's open to debate whether Natural is a subclass or instance of
Accidental.

Roy Smith

unread,
Sep 14, 2008, 3:34:21 PM9/14/08
to
Mr.SpOOn <mr.sp...@gmail.com> wrote:
> Well, from a SharpNote I can obtain the relative NaturalNote. So if I
> have a C# I can call
>
> natural('C#') and get 'C'

And why should you not be allowed to apply natural() to a NaturalNote? I
would think it would just be an identity operator.



> While in the class NaturalNote I don't need such a method, but I need
> two methods to get the sharped and flatted version

Well, you may need sharp() and flat() methods on all notes. Can't you do
sharp('C#'), which should give you C double-sharp?

> > Consider the following code:
> >
> > note1 = SharpNote("E4")
> > note2 = NaturalNote("F4")
> > if note1 == note2:
> > print "the same note"
> > else
> > print "different notes"
> >
> > what should it print?
>
> Well, that's not so simple.

I know it's not simple. I don't know what the correct answer is, or even
if the problem admits to having a single universally correct answer. I'm
just pointing out something you should probably think about.



> Anyway, I think I need an abstract class. Or not?

Hard to tell. My advice would be to start out with a single Note class and
start writing code. If you get to the point where you're writing lots of
conditional logic in your methods (if sharp, do this, if flat, do that),
that's a hint that you may indeed need to refactor things into subclasses.

The next step would be to figure out what the right hierarchy is. Offhand,
I can think of three hierarchies which might be plausible:

------------------------------

Note
SharpNote(Note)
DoubleSharpNote(Note)
FlatNote(Note)
DoubleFlatNote(Note)

This is a relatively flat (sorry about that) hierarchy. Note (arghhh!!)
that there is no explicit NaturalNote class; notes which are not sharp or
flat are just instances of Note.

------------------------------

AbstractNote
NaturalNote(AbstractNote)
SharpNote(AbstractNote)
DoubleSharpNote(AbstractNote)
FlatNote(AbstractNote)
DoubleFlatNote(AbstractNote)

This one sounds like what I think you've currently got in mind.

------------------------------

AbstractNote
NaturalNote(AbstractNote)
SharpNote(AbstractNote)
DoubleSharpNote(SharpNote)
FlatNote(AbstractNote)
DoubleFlatNote(FlatNote)

This one is similar to the above, except that the double-{sharp,flat} note
are subclasses of their single versions.

------------------------------

I have no idea which is the right way to represent this. Some people would
agonize over the decision for days before writing a single piece of code.
My personal preference is to start small, get some code written, and let
the code teach you what makes sense. If things are flowing smoothly, you
probably picked a good way to organize your classes. If things are ugly
and you find yourself writing lots of gnarly conditional code, that's a
hint you're off on the wrong track. Don't be afraid to throw it away and
start from scratch.

BTW, here's another thing to think about. Is a C in a signature where C is
not sharp the same as a C in a signature where it is sharp but written with
a natural accidental? I have no clue, but when you figure out what answer
makes sense for you, that might help you decide how you're going to
organize your classes.

Fredrik Lundh

unread,
Sep 14, 2008, 3:37:16 PM9/14/08
to pytho...@python.org
Mr.SpOOn wrote:

> Well, I know the difference between an abstract class and an inherited
> one. The idea was to create a main class Note, with abstract methods,
> and implement these methods in the other classes.

The pragmatic way to implement abstract classes in Python is to define
an ordinary base class, and either just leave out the methods that must
be defined in subclasses, or provide stub methods that simply raise a
NotImplementedError exception:

class AbstractThing(object):
...
def some_method(self, args):
raise NotImplementedError

There are more "clever" ways to do things, but they're usually overkill.

> Anyway, I think I need an abstract class. Or not?

Depends on how much generally useful functionality you can come up with
for the base class. It's not like Python prevents you from overriding a
non-abstract method, after all.

I suggest you skip further discussion and get to work. I'm sure you'll
figure out what works best for your specific case once you've written a
few classes.

</F>

Roy Smith

unread,
Sep 14, 2008, 3:38:41 PM9/14/08
to
In article
<64670149-9467-4ca7...@c58g2000hsc.googlegroups.com>,

"Aaron \"Castironpi\" Brady" <casti...@gmail.com> wrote:

> However, from what I understand (brass player),

If you play the trombone, you might want your Note class to allow
floating-point values for pitch :-)

Stephen Horne

unread,
Sep 14, 2008, 3:49:24 PM9/14/08
to
On Sun, 14 Sep 2008 18:03:23 +0200, Mr.SpOOn <mr.sp...@gmail.com>
wrote:

>I have to manage many elements of music such as notes, intervals,
>scales, chords and so on. All these elements share properties and
>behavior, so what I want to do is an abstract class "Note" and other
>subclasses, for example "NaturalNote", "FlatNote", "SharpNote" etc.

First off, one approach in Python is to not have a base class at all.
You don't need a base class just to implement a shared interface,
basically. If it walks like a duck and quacks like a duck, you can
usually treat it like a duck, as I think the Ruby crowd say.

Second, it's possible to overdo object orientation, which is probably
Roy Smiths point.

Sometimes, the easiest thing to do is to use a simple integer
representation of your values. With dates, you'd probably use a Julian
day number. That's what spreadsheets usually do, for instance.

With music notes, you'd probably use the note numbers that MIDI uses.

http://www.harmony-central.com/MIDI/Doc/table2.html

You can always extend the range beyond those notes that MIDI supports
if needed.

Doing this means you can switch octaves or transpose using simple
additions or subtractions, for instance. Notes can be decoded using
rounded integer division to find the octave number and the
remainder/modulo % operator (plus maybe a look-up table) to identify
the note.

Use // for integer division (rounded toward -infinity IIRC) or you
risk problems going from Python 2 to Python 3 - the semantics for the
/ division operator are changing. Up until now it would round integer
divisions, but in future it will be considered a "true" non-rounding
division.

This may not work, though, if you aren't working with the
even-tempered scale (if I got that right). There are times when
C-sharp is not the same as D-flat, as MIDI assumes.

You may want to wrap the value in a class, but as far as possible all
your calculations would be based on the integers. Chords might be
represented using either a list or a set - my Python's a little rusty
ATM but IIRC there's a set type based on a dictionary. If you're a
bit-twiddling fan, you might even use a bitvector approach (I don't
think theres a specialised set-of-unsigned-integers bit-vector class
in the library, but I could be wrong). But for most purposes, you'd
probably want the spec. for the chord - "C major" rather than "C, E,
G".

In situations like this, it's sometimes useful to have simple
functions in a module, or else a 'tool' class (which works on the
values, but only encapsulates the tools own state). You can still wrap
the values in a class with a common interface. The point of this is
that it's relatively easy to share functionality when you implement
some value-wrapper classes in several different ways - e.g. note-set
chords vs. specification-based chords, note-number representations vs.
string representations, etc.

That is, in object oriented theory, the object manipulates itself -
but that doesn't always work so well in practice, especially for
functions that deal with two or more objects. As in the real world, a
tool sometimes works better. And if the tool doesn't need any state,
it may as well be a single procedure/function in a module rather than
a class.

Aaron "Castironpi" Brady

unread,
Sep 14, 2008, 3:49:51 PM9/14/08
to
On Sep 14, 2:38 pm, Roy Smith <r...@panix.com> wrote:
> In article
> <64670149-9467-4ca7-9d7e-c330c1b40...@c58g2000hsc.googlegroups.com>,

>  "Aaron \"Castironpi\" Brady" <castiro...@gmail.com> wrote:
>
> > However, from what I understand (brass player),
>
> If you play the trombone, you might want your Note class to allow
> floating-point values for pitch :-)

I do! Then there are the known cases of flute players rolling the
mouthpiece to change pitch, trumpet players bending, violin. The 3rd
of a scale is slightly sharp in Bach's temper. Semi-tones come up in
Theory class too.

note= Note( "C" )
third= MajorInterval( 3 )
print note+ third
: <NaturalNote("E"), slightly flat>

Gabriel Genellina

unread,
Sep 14, 2008, 3:50:30 PM9/14/08
to pytho...@python.org
En Sun, 14 Sep 2008 16:15:04 -0300, Gary Herron
<ghe...@islandtraining.com> escribió:

> Please forget about Abstract Base Classes. They have nothing to do with
> what you want, and are a *HUGE* overkill for your application. They
> are not (yet) even part of standard Python, and are used primarily for a
> class implementor to guarantee to a user of a class that it provides a
> specific interface.

Just to say that abstract classes *are* already available in Python 2.6:

Python 2.6rc1+ (trunk, Sep 13 2008, 11:29:39) [MSC v.1500 32 bit (Intel)]
on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import abc
>>> help(abc.abstractmethod)
Help on function abstractmethod in module abc:

abstractmethod(funcobj)
A decorator indicating abstract methods.

Requires that the metaclass is ABCMeta or derived from it. A
class that has a metaclass derived from ABCMeta cannot be
instantiated unless all of its abstract methods are overridden.
The abstract methods can be called using any of the the normal
'super' call mechanisms.

Usage:

class C(metaclass=ABCMeta):
@abstractmethod
def my_abstract_method(self, ...):
...

--
Gabriel Genellina

Steven D'Aprano

unread,
Sep 14, 2008, 4:25:18 PM9/14/08
to
On Sun, 14 Sep 2008 12:15:04 -0700, Gary Herron wrote:

> (If you wish to consider the base class "abstract", just agree with
> yourself to not instantiate it.)

That's certainly the most lightweight option.


> Please forget about Abstract Base Classes. They have nothing to do with
> what you want, and are a *HUGE* overkill for your application. They
> are not (yet) even part of standard Python, and are used primarily for a
> class implementor to guarantee to a user of a class that it provides a
> specific interface.


You can implement a lightweight abstract base class in Python fairly
easily, by adding two lines to the __init__ method of your base class.


class Base(object):
def __init__(self):
if self.__class__ is Base:
raise NotImplementedError("Abstract base class")
def method(self, *args):
return len(args) # or something useful


If you want to get fancy, you can define a custom exception instead of
using NotImplementedError. And that's about all you need. You can get
more complicated if you want, but why bother?

If I may be excused a slight digression, I don't get the "abstract" part
of ABCs. The prohibition against instantiating them just seems very
artificial, I don't see what benefit it gets you. Wikipedia says:

"The fact that many languages disallow instantiation of abstract types
(and force subtypes to implement all needed functionality) further
ensures program correctness."

http://en.wikipedia.org/wiki/Abstract_base_class

but I don't see how that follows (except possibly in very special cases).
Given that the set of instances of class B is empty, how does that help
you know that B.method is correct?

--
Steven

Stephen Horne

unread,
Sep 14, 2008, 4:28:19 PM9/14/08
to
On Sun, 14 Sep 2008 21:19:06 +0200, Mr.SpOOn <mr.sp...@gmail.com>
wrote:

>I started to think to abstract classes just because in the paper it
>uses an abstract class in SmallTalk.

FWIW, it was obvious to me that you was using the term "abstract" in
the wider sense. You did say about the Smalltalk paper, after all. And
to me, any Python class that you treat as abstract is abstract. That
was always how the word "abstract" was used by Python users in the
past.

Now, it seems that there's a specific Python feature to enforce
abstractness. That's nice to know, and I'll have to do some reading.
As I said elsewhere, my Python's getting a bit rusty. But I doubt I'll
use it for the "overkill" reason. To me, the last important feature
added to Python was conditional expressions in 2.5 IIRC, and while I
love some features that others see as bloat, there's a lot that came
in earlier versions that I'm never likely to use.

For example, to me the term "property" is basically a trivial design
pattern or an object-oriented principle. I don't really see the need
for the language feature. I can define getter and setter methods all
by myself, and I don't really see the benefit of disguising them as
member variables. I used to like the idea, but now I'm more of an
occasional Python user, I can't be bothered looking up the syntax.

It's a strange role reversal - I used to be very enthusiatic about new
features back when others kept saying Python 1.5 is all you need.

Stephen Horne

unread,
Sep 14, 2008, 4:46:08 PM9/14/08
to
On 14 Sep 2008 20:25:18 GMT, Steven D'Aprano
<st...@REMOVE-THIS-cybersource.com.au> wrote:

>"The fact that many languages disallow instantiation of abstract types
>(and force subtypes to implement all needed functionality) further
>ensures program correctness."
>
>http://en.wikipedia.org/wiki/Abstract_base_class
>
>but I don't see how that follows (except possibly in very special cases).
>Given that the set of instances of class B is empty, how does that help
>you know that B.method is correct?

That's the point - to be certain that the set of instances of class B
really is empty.

As for B.method, it's correctness isn't purely determined by the code
of the method itself. It will usually depend on the object being in a
self-consistent state. It's often impossible for an instance of an
abstract base to have a self-consistent state. Therefore, it's better
to guarantee that no instances can be accidentally created.

OTOH, this argument is often an over-pedantic technicality. You can't
eliminate all errors from code by making the language stricter.
Instantiating an abstract class isn't a very common error in my
experience. Whether detecting it is a priority depends on what you're
doing.

Mr.SpOOn

unread,
Sep 14, 2008, 6:08:53 PM9/14/08
to pytho...@python.org
It seems I started a long discussion.

You pointed out a lot of interesting things. For example the math
operations over notes and intervals and the use of the modulo
operator. I already had in mind to implement such things.

Anyway, the real purpose of the project is to use these objects with
Pyke (Python Knowledge Engine) [1]. I'm not sure yet what I am going
to do, but and idea would be to find an appropriate scale for some
given chords (for example, from a midi input).

As suggested, I'm going to write code and see what is better.

Thanks everybody,
bye


[1] http://pyke.sourceforge.net/

Bruno Desthuilliers

unread,
Sep 15, 2008, 8:10:04 AM9/15/08
to
Stephen Horne a écrit :
(snip)

> For example, to me the term "property" is basically a trivial design
> pattern or an object-oriented principle. I don't really see the need
> for the language feature. I can define getter and setter methods all
> by myself, and I don't really see the benefit of disguising them as
> member variables.

The canonical use case for computed attributes is that they let you turn
a plain attribute into a computed one if/when the need arises, without
breaking client code *nor* having to force all access attributes thru
getters/setters righ from the start "just in case".

Maric Michaud

unread,
Sep 15, 2008, 8:09:13 AM9/15/08
to pytho...@python.org
Le Sunday 14 September 2008 22:25:18 Steven D'Aprano, vous avez écrit :
> On Sun, 14 Sep 2008 12:15:04 -0700, Gary Herron wrote:
> > (If you wish to consider the base class "abstract", just agree with
> > yourself to not instantiate it.)
>
> That's certainly the most lightweight option.
>
> > Please forget about Abstract Base Classes. They have nothing to do with
> > what you want, and are a *HUGE* overkill for your application. They
> > are not (yet) even part of standard Python, and are used primarily for a
> > class implementor to guarantee to a user of a class that it provides a
> > specific interface.
>
> You can implement a lightweight abstract base class in Python fairly
> easily, by adding two lines to the __init__ method of your base class.
>
>
> class Base(object):
> def __init__(self):
> if self.__class__ is Base:
> raise NotImplementedError("Abstract base class")
> def method(self, *args):
> return len(args) # or something useful
>
>

But this doesn't match what abstract classes are (in C++ for example), because
__init__ can, and probably will, have logic reusable in concrete classes. The
only way to do this is to call in the __int__ at least one of the methods
raising NotImplementedError, probably creating a dummy one for this purpose,
and still it doesn't satisfy with the constraint that *all* abstract methods
must be implemented in concrete classes.

> "The fact that many languages disallow instantiation of abstract types
> (and force subtypes to implement all needed functionality) further
> ensures program correctness."
>
> http://en.wikipedia.org/wiki/Abstract_base_class
>
> but I don't see how that follows (except possibly in very special cases).
> Given that the set of instances of class B is empty, how does that help
> you know that B.method is correct?

I agree with you on this, and the simple scheme of defining some methods
raising exceptions is obviously sufficiient where duck typing is.

ABC, as I understood it, is for resolving another problem : unrelated (by
inheritance) classes, which share the same signature, but need to be
distinguished in their behavior.

--
_____________

Maric Michaud

Roy Smith

unread,
Sep 15, 2008, 8:58:54 AM9/15/08
to
Maric Michaud <ma...@aristote.info> wrote:

> The only way to do this is to call in the __init__ at least one of the

> methods raising NotImplementedError, probably creating a dummy one for
> this purpose, and still it doesn't satisfy with the constraint that
> *all* abstract methods must be implemented in concrete classes.

I wouldn't actually *call* the method (because of possible side-effects),
but you could certainly check that they exist and are callable:

class Base:
"""An abstract base class. You must define methods f(),
g(), and h() in any subclasses of this.
"""

def __init__(self):
try:
assert callable(self.f)
assert callable(self.g)
assert callable(self.h)
except:
raise NotImplementedError # or something more specific

Of course, this assumes that you write:

class Derived(Base):
def __init__(self):
Base.__init__(self)

There's no way (that I can think of :-)) to *force* you to call
Base.__init__() from Derived.__init__().

This is all a bit silly, however. If you want type bondage, use a language
that gives you type bondage (C++ and Java being two obvious examples).

Fredrik Lundh

unread,
Sep 15, 2008, 10:42:49 AM9/15/08
to pytho...@python.org
Maric Michaud wrote:

> But this doesn't match what abstract classes are (in C++ for example)

you're confusing concepts with specific implementations of those
concepts here.

</F>

Maric Michaud

unread,
Sep 15, 2008, 11:02:45 AM9/15/08
to pytho...@python.org

Maybe, that's why I gave this example, but aren't they (conceptually)
classes :

- which couldn't be instantiated,
- which define at least an interface and possibly some behavior,
- for which all the undefined methods need to be implemented in concrete
classes (the pure virtual methodds in C++)

?

That's the exact implementation in C++ but I'm not aware of any other language
that implement this notion. Java simplified this a lot, abstracts are
interface (type), no behavior.

--
_____________

Maric Michaud

0 new messages