From: Gabriel Genellina on
En Tue, 09 Mar 2010 18:26:52 -0300, Andrey Fedorov <anfedorov(a)gmail.com>
escribi�:

> So I have `x', a instance of class `Foo'. I also have class `Bar', a
> class
> extending `Foo' with a couple of methods. I'd like to "down cast" x as
> efficiently as possible. Is it OK to just set `x.__class__ = Bar' and
> expect
> things to work OK in all major versions of CPython?

If the assignment x.__class__ = Bar succeeds, yes, that's enough. But you
may not be able to reassign __class__ in some cases (e.g. Foo defines
__slots__ but Bar doesn't, so you have a layout conflict).

Of course, you always have to make sure Bar invariants hold on this
particular instance...

I must ask, why you didn't create a Bar instance in the first place?

--
Gabriel Genellina

From: Steve Holden on
Andrey Fedorov wrote:
> On Wed, Mar 10, 2010 at 12:24 AM, Rami Chowdhury
> <rami.chowdhury(a)gmail.com <mailto:rami.chowdhury(a)gmail.com>> wrote:
>
> Could you tell us *why* you need to down-cast x? Explicit
> type-casting is usually unnecessary in Python...
>
>
> Sure! It's related to the longer question I unwisely asked during PyCon
> [1] (when no one had time to read it, I suppose).
>
> I have a couple of different flavors of request objects which I'd like
> to make conform to a single interface. So Request `x' come in, I
> determine which kind of request I'm dealing with, and would like to
> "down-cast" it to ARequest or BRequest, classes which will provide
> appropriate accessor properties for the rest of the code to use.
>
> An option clearly in line with Python's docs might be for `x' to be an
> attribute of an ARequest instance, but that would complicate the code of
> ARequest. What I'm looking for is a way of adding mix-in's at runtime,
> if that makes sense.
>
The technique you need is not inheritance (which you are really trying
to abuse here, IMHO) but delegation.

Since all requests start out as of the same type, why not just give each
request a handler attribute and set it to a BarHandler or FooHandler
instance as appropriate. Then your generic code can call the handler's
methods, obtaining Foo- or Bar-style behavior as appropriate. If the
handler needs to manipulate the request object then the request object
can pass itself in as a method argument.

Technically your requests are delegating the handling to a subsidiary
object which implements the correct behavior for the request type.

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
See PyCon Talks from Atlanta 2010 http://pycon.blip.tv/
Holden Web LLC http://www.holdenweb.com/
UPCOMING EVENTS: http://holdenweb.eventbrite.com/