downcasting problem

N

Nikola Skoric

Hi everybody,

I need to downcast an object, and I've read repeatedly that if you
need to downcast, you did something wrong in the design phase. So,
instead of asking how do you downcast in python, let me explain my
situation.

I have a 2-pass parser. 1st pass ends up with a bunch of superclass
object, and 2nd pass is supposed to downcast those to one of
subclasses so I can work with them.

Details:

I have a file full of lines which I parse into Line objects. I also
have two subclasses of Line, namely Individual and Family. Constructor
of both subclasses needs all Line objects in the file to be
constructed, so I cannot construct subclass objects in the first pass.

The Python way of doing this (as I understand it) would be to wrap a
subclass around Line and have the Line object as an attribute of a
subclass. Now, this obviously breaks polymorphism and I now have to
reimplement all of Line's classes in subclasses. Although
reimplementation is simple (def method(self): return
self.line.method()), that way of doing things is just not elegant.

So, is there any more elegant solution to my problem?

Thanks in advance.
 
T

Tim Chase

While a dirty hack for which I'd tend to smack anybody who used
it...you *can* assign to instance.__class__
.... def __init__(self, name):
.... self.name = name
.... def __str__(self): return self.name
........ def foo(self): print "I'm B: %r" % self.name
........ def foo(self): print "I'm C: %r" % self.name
....I'm C: 'Alpha'


If it breaks you get to keep all the parts :)

-tkc
 
N

Nikola Skoric

Dana Mon, 25 Oct 2010 09:38:42 -0500,
Tim Chase said:
While a dirty hack for which I'd tend to smack anybody who used
it...you *can* assign to instance.__class__

Wow! Python never stops to amaze me.
If it breaks you get to keep all the parts :)

Yes, I can see great potential for shit hitting the fan here.

Thanks for the tip!
 
J

John Nagle

While a dirty hack for which I'd tend to smack anybody who used it...you
*can* assign to instance.__class__

That's an implementation detail of CPython. May not work in
IronPython, Unladen Swallow, PyPy, or Shed Skin.

(An implementation with a JIT has to trap stores into some
internal variables and invalidate the generated code.
This adds considerable complexity to the virtual machine.
Java JVMs, for example, don't have to support that.)

John Nagle
 
E

Emmanuel Surleau

Hi everybody,
I need to downcast an object, and I've read repeatedly that if you
need to downcast, you did something wrong in the design phase. So,
instead of asking how do you downcast in python, let me explain my
situation.

I have a 2-pass parser. 1st pass ends up with a bunch of superclass
object, and 2nd pass is supposed to downcast those to one of
subclasses so I can work with them.

Details:

I have a file full of lines which I parse into Line objects. I also
have two subclasses of Line, namely Individual and Family. Constructor
of both subclasses needs all Line objects in the file to be
constructed, so I cannot construct subclass objects in the first pass.

The Python way of doing this (as I understand it) would be to wrap a
subclass around Line and have the Line object as an attribute of a
subclass. Now, this obviously breaks polymorphism and I now have to
reimplement all of Line's classes in subclasses. Although
reimplementation is simple (def method(self): return
self.line.method()), that way of doing things is just not elegant.
So, is there any more elegant solution to my problem?

Why not have an abstract Line class with your Line methods, a SimpleLine (your
current Line class, extends AbstractLine), and IndividualLine and FamilyLine
(both extending AbstractLine)?

Cheers,

Emm
 
D

Diez B. Roggisch

Nikola Skoric said:
Hi everybody,

I need to downcast an object, and I've read repeatedly that if you
need to downcast, you did something wrong in the design phase. So,
instead of asking how do you downcast in python, let me explain my
situation.

I have a 2-pass parser. 1st pass ends up with a bunch of superclass
object, and 2nd pass is supposed to downcast those to one of
subclasses so I can work with them.

This is usually called a 'reducer' in parsing, and it's purpose is to
rewrite the parsing result to something new.

It's usually implemented using a visitor-pattern.

In your case, it should be rather straightforward, by simply iterating
over the objects and creating new, more specialized types depending on
what you actually need.

So you don't need to delegate anything.

Diez
 
T

Tim Chase

That's an implementation detail of CPython. May not work in
IronPython, Unladen Swallow, PyPy, or Shed Skin.

Curious by your claim, could you confirm this someplace in the
docs? From my reading of [1]'s "If x is an instance of a
new-style class, then type(x) is typically the same as
x.__class__ (although this is not guaranteed - a new-style class
instance is permitted to override the value returned for
x.__class__)" is that this can be overridden (the definition of
"overridden" however may mean different things to different
people) and [2] refers to "__class__ assignment works only if
both classes have the same __slots__" (that seems pretty clear
that __class__ assignment is permissible)

-tkc


[1]
http://docs.python.org/reference/datamodel.html#new-style-and-classic-classes

[2]
http://docs.python.org/reference/datamodel.html#__slots__
 
H

Hrvoje Niksic

John Nagle said:
That's an implementation detail of CPython. May not work in
IronPython, Unladen Swallow, PyPy, or Shed Skin.

(An implementation with a JIT has to trap stores into some
internal variables and invalidate the generated code.
This adds considerable complexity to the virtual machine.
Java JVMs, for example, don't have to support that.)

A Python implementation probably looks up attributes via type late at
runtime anyway, so modifying __class__ boils down to changing a
reference inside the (moral equivalent of the) PyObject structure.

For example, assigning to __class__ appears to work just fine in Jython
2.5.2:

Jython 2.5.2rc2 (Release_2_5_2rc2:7167, Oct 24 2010, 22:48:30)
[OpenJDK 64-Bit Server VM (Sun Microsystems Inc.)] on java1.6.0_18
Type "help", "copyright", "credits" or "license" for more information..... pass
.... <__main__.Y object at 0x3>
 
L

Lawrence D'Oliveiro

I have a file full of lines which I parse into Line objects. I also
have two subclasses of Line, namely Individual and Family. Constructor
of both subclasses needs all Line objects in the file to be
constructed, so I cannot construct subclass objects in the first pass.

Circularity of reference which does not fit into the object-oriented
insistence on a hierarchy. So the only way around it is to introduce more
layers of complications which get you further way from solving the original
problem.

Tell me again, what relevance OO has to the real world?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top