Alexander Schmolck wrote:
...
To recap: usually, if I change a class I'd like all pre-existing instances
to become updated (Let's say you develop your program with a running
If you CHANGE a class (mutate a class object), that does indeed happen.
You seem to have some deep level of confusion between "changing an
object" and "rebinding a name (that happened to be previously bound
to a certain object) so it's now bound to a different object".
Rebinding a name *NEVER* has any effect whatsoever on the object that
might have, by happenstance, previously bound to that name (except that,
when _all_ references to an object disappear, Python is free to make
that object disappear whenever that's convenient -- but that doesn't
apply here, since if a class object has instances it also has references
to it, one per instance).
This rule is universal in Python and makes it trivially simple to
understand what will happen in any given occasion -- just as long
as you take the minimal amount of trouble to understand the concepts
of names, objects, binding (and rebinding) and mutation. If a language
has no such clear universal rule, you're likely to meet with either
deep, complex trouble, or serious limitations with first-classness
of several kinds of objects. In Python everything is first-class,
and yet there is no substantial confusion at all.
Repeat with me: rebinding a name has just about NOTHING to do with
mutating an object. These are VERY different concepts. Until you
grasp them, you won't be a very effective programmer.
python session; you notice a mistake in a method-definition but don't want
to start over from scratch; you just want to update the class definition
and have this update percolate to all the currently existing instances.
I assume that by "update the class definition" you mean that you want
*necessarily* to use some:
class X: ...
statement that defines a NEW class object (which may happen to have
the same name as an existing class object -- quite irrelevant, of
course). OK, then, so arrange (easily done with some function or
editing macro, if you have a decent editor / IDE) to do the following:
oldX = X # save the existing classobject under a new temporary name
class X: ... # define a completely new and unrelated classobject
oldX.__dict__.clear()
oldX.__bases__ = X,
# in case you also want to change the old class's name, you might:
oldX.__name__ = X.__name__ # so you're not constrained in this sense
# optionally, you can now remove the temporary name
del oldX
There. What's so hard about this? How does this fail to meet your
desiderata? Wouldn't it have been easier to ask, in the first place,
"I would like to obtain this effect, is there a Python way" (being
a BIT more precise in describing "this effect", of course!-), rather
than whining about "Python can't do this" and complaining of this as
being "unreasonable"?
AFAIK doing this in a general and painfree fashion is pretty much
impossible in python (you have to first track down all instances -- not an
I personally wouldn't dream of doing this kind of programming in production
level code (and I'd have a serious talk with any colleague doing it -- or
changing __class__ in most cases, etc). But depending on one's development
style and usage it may perhaps be helpful. If I did that often, of course,
I would ensure that the simple function:
def updateClass(oldClass, newClass):
oldClass.__dict__.clear()
oldClass.__bases__ = newClass,
oldClass.__name__ = newClass.__name__
was automatically loaded at entry in the interactive environment (see e.g.
the PYTHONSTARTUP environment variable for doing this in the usual text-mode
interactive interpreter).
I think this sucks big time, because it greatly devalues the interactive
programming experience for certain tasks, IMHO, but maybe I'm just missing
something since typically nobody complains.
I don't think the fact that nobody complains is strongly connected to the
fact that most Python users grasp the possibility of updating a class by
modyfying its __dict__ etc; indeed, one great thing about Python is that
most users typically tend to SIMPLICITY rather than "cleverness" -- if they
wanted to modify a class X's method Y they'd code it as a function F and
then simply do X.Y=F -- extremely simple, rapid, effective, and no need
to much with redoing the whole 'class' statement (a concept I personally
find quite terrible). Rarely does one want to modify an existing class
object any more 'deeply' than by just redoing a method or two, which this
utterly simple assignment entirely solves -- therefore, no real problem.
If your style of interactive programming is so radically different from
that of most other Pythonistas, though, no problem -- as you see, if you
put some effort in understanding how things work (particularly the
difference between *MODIFYING AN OBJECT* and *REBINDING A NAME*), Python
supports you with power and simplicity in MOST (*NOT* all) metaprogramming
endeavours.
If you DO want total untrammeled interactive and dynamic metaprogramming
power, though, *THEN* that's an area in which Ruby might support you
even better -- for example, this Python approach would *NOT* work if
oldClass was for example str (the built-in string class -- you CANNOT
modify ITS behavior). Personally, for application programming, I much
prefer clear and well-defined boundaries about what can and what just
CANNOT change. But if you want EVERYTHING to be subject to change, then
perhaps Ruby is exactly what you want. Good luck with keeping track
of what names are just names (and can be freely re-bound to different
objects) and which ones aren't (and are more solidly attacked to the
underlying objects than one would expect...).
Alex