On Sun, 14 Sep 2008 18:03:23 +0200, Mr.SpOOn <[EMAIL PROTECTED]> 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. -- http://mail.python.org/mailman/listinfo/python-list