Dynamically replacing an objects __class__; is it safe?
jladasky at itu.edu
jladasky at itu.edu
Fri Mar 17 17:44:23 EDT 2017
On Thursday, March 16, 2017 at 7:07:17 PM UTC-7, Deborah Swanson wrote:
> Steve D'Aprano wrote,on March 16, 2017 5:07 AM
> > On Thu, 16 Mar 2017 09:03 am, Gregory Ewing wrote:
> > > Steve D'Aprano wrote:
> > >> You probably can't make a whale fly just by changing the class to
> > >> bird. It will need wings, and feathers, at the very least.
> > >
> > > Some things succeed in flying with neither wings nor feathers.
> > > Helicopters, for example.
> > For some definition of "no wings".
> > But regardless of rockets, balloons, helicopters, Boeing 747s
> > and Dr Strange's mystical Cloak Of Levitation, *birds*
> > require wings and feathers to fly. If you just paint "BIRD"
> > on the side of a whale, it won't get off the ground, and if
> > you do manage to get it airborne (via a catapult,
> > perhaps) it will just come down with a rather large splat.
> > The point is that dynamically swapping the class of an
> > existing instance at runtime is *not* just a way of doing
> > duck-typing. It really does matter if your duck flies by
> > flapping feathered wings or by blasting an exhaust of hot
> > gasses out of its rear end at high speed.
> > With duck-typing, you don't care whether you have a duck or a
> > goose, so long as they both can fly: you don't care *how* it
> > flies, so long as it does, and even a rocket-propelled
> > balloon will be fine.
> > But when you dynamically swap out __class__ (I think
> > Objective-C "swizzling" is conceptually equivalent, so I'll
> > call it by that word) you have to care about the
> > implementation. The whole point of swizzling is that it
> > allows you to swap out one implementation ("run forward and
> > flap your wings") with another implementation ("light the
> > blue touch paper"). But if you do that, you have to care
> > about implementation details. There's no point in setting
> > your swizzled fly() method to that of Rocket if your instance
> > doesn't have blue touch paper to light.
> > With duck-typing, making the methods work isn't your
> > responsibility. But when you swizzle, you are responsible for
> > making sure that the instance provides whatever the methods
> > need to work.
> > A very old but good example of Python swizzling is here:
> > http://code.activestate.com/recipes/68429-ring-buffer/
> "Cheer up," they said, "things could be worse." So I cheered up, and
> sure enough, things got worse.
> Condolences, Steve. Nobody on this thread wants to plumb the depths of
> Python swizzling. Or anything else Python, so it appears.
If you're getting discouraged by a certain spammer who posts to this newsgroup in ALL CAPS and ITALIAN, don't let him beat you. Go find newsreader software that allows you to define filters and killfiles. It will help.
If you read further into that article about the RingBuffer class and "swizzling", Steve Alexander suggests a method that I have used myself, and which I consider to be generally superior: conditionally rebinding the names of methods you want to change within a class, rather than overriding __class__ itself.
I suppose that each approach has its merits. If you want the object's type to advertise that a condition has changed, rebinding __class__ is good. If you have many methods to change, and you don't like long lists of similarly-named functions in one class, rebinding __class__ could also be good.
I don't encounter those conditions much myself. In the RingBufferFull case, only two methods need to change, .append() and .get(). Both methods are short. Both methods' eventual replacements, which we might name ._full_append() and ._get(), are also short. I would do it Steve Alexander's way.
More information about the Python-list