'isa' keyword

talin at acm dot org viridia at gmail.com
Fri Sep 2 13:06:41 EDT 2005


Thanks for all the respones :) I realized up front that this suggestion
is unlikely to gain approval, for reasons eloquently stated above.
However, there are still some interesting issues raised that I would
like to discuss.

Let me first respond to a few of the comments:

>What's the difference between this and ``isinstance`` ?

What's the difference between 'in' and 'has_key()"? 1) Its shorter and
more readable, 2) it can be overridden to mean different things for
different container types.

> What's wrong with:
>     if image.isa(gif):
>     elif image.isa(jpeg):
>    elif image.isa(png):

That forces the classification logic to be put into the instance,
rather than in the category. With the "in" keyword, the "__contains__"
function belongs to the container, not the contained item, which is as
it should be, since an item can be in multiple containers.

> Especially conidering that checking parameters with "isinstance" is
> considered bad form with Python's duck typing.

Here's an example where the strict OOP style of programming breaks
down. I'll use SCons as an example. In SCons, there is a "Depends"
function that can take a filename, a list of filenames, or a build
target (which is a python object). So the logic looks like this:

def Depends( target ):
   if isinstance( target, str ):
        ...
   elif isinstance( target, list ):
       ...
   elif isinstance( target, BuildTarget ):
       ...
   else: error

You can't use method overloading here, because you are dealing with
builtin python objects (except for the BuildTarget).

I can think of several different cases where you would have to resort
to logic like this:
  -- Where you are trying to distinguish between built-n python types
  -- Where you are trying to distinguish between types that are created
by another, independent module and which you can't modify
  -- Where you are trying to do multi-method dispatch logic.

As an example of the latter, imagine a music sequencer application that
edits a stream of Midi events. Lets suppose that there are various
"classes" of events:

   Note On
   Note Off
   Aftertouch
   Pitchbend
   Control Change

In addition, lets suppose that we  have a variety of different ways of
editing these events:

   "Piano Roll" Editor - edits in horizontal "piano roll" form
   "Drum Machine" editor - notes are placed on a grid
   Event List Editor - a text list of events
   Music Notation Editor - uses conventional notes and staves

All of these editors operate on the same underlying data, which is a
stream of events. Each of these editors has a "repaint" function to
render the stream of events. So the rendering of the event depends
*both* on the class of the event, and the class of the editor.

So you could organize it this way:

class PianoRollEditor:
   def repaint( event ):
      if isinstance( event, Note ): # draw note
      elif isinstance( event, Aftertouch ): # draw
      ...etc

You could also invert the logic (which is somewhat clumsier):

class Note:
   def repaint( context ):
      if isinstance( context, PianoRollEditor ): ...
      etc...

Now, I realize that some folks have built multi-method dispatch systems
for Python (I did one myself at one point.) However, these tend to be
somewhat slow and clunky without language support (and no, I am not
asking for Python to become Dylan or CLOS.) But it would be nice to
know if there was a cleaner way to solve the above problems...




More information about the Python-list mailing list