Is there a reason not to do this?

Carl Banks pavlovevidence at gmail.com
Thu Nov 30 22:05:12 EST 2006


Ron Garret wrote:
> In article <4t96ujF134nv7U1 at mid.uni-berlin.de>,
>  "Diez B. Roggisch" <deets at nospam.web.de> wrote:
>
> > Ron Garret schrieb:
> > > One of the things I find annoying about Python is that when you make a
> > > change to a method definition that change is not reflected in existing
> > > instances of a class (because you're really defining a new class when
> > > you reload a class definition, not actually redefining it).  So I came
> > > up with this programming style:
> > >
> > > def defmethod(cls):
> > >   return lambda (func): type.__setattr__(cls, func.func_name, func)
> > >
> > > class c1(object): pass
> > >
> > > @defmethod(c1)
> > > def m1(self, x): ...
> > >
> > >
> > > Now if you redefine m1, existing instances of c1 will see the change.
> > >
> > > My question is: is there a reason not to do this?  Does it screw
> > > something up behind the scenes?  Is it unpythonic?  Why isn't this
> > > standard operating procedure?

1. Do you mean, is there an "it'll crash the interpreter" reason? No.
2. Not for most ordinary cases.  There are a few gotchas (for example,
use of __private variables), but they're minor.
3. Yes.
4. Because it's unPythonic.

But don't worry too much if you do something unPythonic occasionally.
Python says there's should be one--and preferably only one--obvious way
to do it.  So if there's no obvious way to do it, you probably have to
do something unPythonic.  (Or consult someone with more experience. :)


[snip]
> I have two motivations.
>
> First, I'm dealing with some classes whose instances take a long time to
> construct, which makes for a long debug cycle if I have to reconstruct
> them after every code change.
>
> Second, the design just naturally seems to break down that way.  I have
> a library that adds functionality (persistence) to a set of existing
> classes.  The persistence code stores the objects in a relational DB, so
> it's pretty hairy code, and it has nothing to do with the functionality
> that the classes actually provide.  The original classes are useful even
> with the persistence code, and I'm trying to keep things lightweight.

Seems like a reasonable use case to me.

> If there's a better way to accomplish all this I'm all ears.

A straightforward, Pythonic way to do it would be to create an
intermediate representation that understands both the existing class
interfaces and the RDB stuff, but that could lead to synchronizing
problems and a big hit in performance.  And it's probably a lot of work
compared to tacking on methods.  OTOH, it could help with hairiness you
mention.  (I recently did something similar in one of my projects,
though the intermediary was transient.)

You might be able to create a set of augmented subclasses to use
instead.  The main problem with this is that base classes often don't
know about the augmented versions.  You'd have to override code that
requires an ordinary object with code that allows an augmented object.
This is sometimes very inconvenient (like when the code requiring an
ordinary object is one line smack in the middle of a 100-line
function).

It actually sounds like Aspect Oriented Programming might be helpful
here (if you care to learn another wholly different programming
paradigm, that is).  You have a concern (persistence) that's pretty
much off in another dimension from the purpose of the classes.


Or maybe the best way is just to teach an old class new tricks.


Carl Banks




More information about the Python-list mailing list