poppopjmp / shedskin

Automatically exported from code.google.com/p/shedskin
0 stars 0 forks source link

(Maybe) __to_py__ should be virtual #185

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
This is a long one, bear with me.
First of all, download the two attached files.

Run shedskin -e to_py_mod.py
IMPORTANT: Everytime you do this, modify the hpp file so that the method 
Shape.draw is virtual (related to this 
https://code.google.com/p/shedskin/issues/detail?id=184).

Now execute python to_py.py

This will be the output:

<to_py_mod.Shape object at 0xb75550f0>
<to_py_mod.Shape object at 0xb75550e0>
Rectangle.draw and Circle.draw
(<built-in function __newobj__>, (<type 'to_py_mod.Manager'>,), 
(<to_py_mod.Shape object at 0xb75550e0>, <to_py_mod.Shape object at 
0xb75550f0>))
<to_py_mod.Shape object at 0xb75550d0>
<to_py_mod.Shape object at 0xb7555110>
Shape.draw and Shape.draw

Notice how the first two lines print object of the type Shape. In reality, they 
are of the types Rectangle and Circle.
You can tell in the third line that even though they look like generic shapes, 
they behave as expected due to polymorphism (printing "Rectangle.draw and 
Circle.draw").

The next line shows the output of manager.__reduce__. Notice how here also the 
types are Shape.

The problem is that pickling and unpickling will result in an object that will 
behave differently because now shape1 and shape2 are now really of the type 
Shape instead of Rectangular and Circular.

One solution that I see is to make the method __to_py__ virtual.
If you do that, then this is the output:

<to_py_mod.Rectangle object at 0xb74d70f0>
<to_py_mod.Circle object at 0xb74d70e0>
Rectangle.draw and Circle.draw
(<built-in function __newobj__>, (<type 'to_py_mod.Manager'>,), 
(<to_py_mod.Circle object at 0xb74d70e0>, <to_py_mod.Rectangle object at 
0xb74d70f0>))
<to_py_mod.Rectangle object at 0xb74d70d0>
<to_py_mod.Circle object at 0xb74d7110>
Rectangle.draw and Circle.draw

One odd thing is that if you replace the line:

manager = Manager(Rectangle(), Circle())

with:

rectangle = Rectangle()
circle = Circle()
manager = Manager(rectangle, circle)

also solves the problem. But I don't think that's clear or obvious for an user. 
I have a somewhat complex program where this is causing me problems.
And in that program, making the __to_py__ method virtual solves the problem.

On the same note, why can't all methods defined by the user be virtual? 
Wouldn't that represent the actual behaviour in Python?
And if all the method can be virtual, that would simplify the implementation 
shedskin.

Any thoughts on this?

Original issue reported on code.google.com by ernestof...@gmail.com on 7 Mar 2013 at 3:16

Attachments:

GoogleCodeExporter commented 8 years ago
performance for __to_py__ is not an issue in any case, because conversion is 
known to be slow already. adding a virtual keyword sounds like a good solution 
to me! 

Original comment by mark.duf...@gmail.com on 7 Mar 2013 at 8:05

GoogleCodeExporter commented 8 years ago
Excellent!

Original comment by ernestof...@gmail.com on 7 Mar 2013 at 8:20

GoogleCodeExporter commented 8 years ago
change committed, thanks again for this!

Original comment by mark.duf...@gmail.com on 9 Mar 2013 at 7:28