473,769 Members | 2,331 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

subclassing extension type and assignment to __class__

Hello,

I am currently writing python bindings to an existing C++ library, and I
just encountered a problem that I hope has been solved by more
experienced python programmers:

A C++ class (let's call it CClass) is binded using classical Python
extension API to _PClass, which is accesible through python without any
problem. The problem is that I want this class to be extended/extensible
in python, and expose the python-extended version (PClass) to library
users (_PClass should never be used directly nor be retruned by any
function).
The aim is to leave only performance critical methods in C++ so that the
binding work is minimal, and develop the other methods in python so that
they are easier to maintain/extend.

We thus have something like this

class PClass(_PClass) :
def overide_method( self,...):
...
def new_method(self ,...):
...

and I can define
a=PClass()
and use my new or overiden method
a.overide_metho d() a.new_method() as intended...

So far, so good, trouble begin when I have a method from another class
PClass2 derived from _PClass2 which bind the C++ class CClass2, that
should return objects of type PClass:

Let call this method troublesome_met hod:

b=_PClass2()
c=b.troublesome _method()
type(c) gives _PClass.

now I want to define a python class PClass2 for extending methods of
_PClass2 like I have done for _PClass, in particular I want that PClass2
troublesome_met hod return objects of type PClass instead of _PClass...

To this end I try something like this

class PClass2(_PClass 2):
...
def troubelsome_met hod(self):
base=_PClass2.t roublesome_meth od(self)
base.__class__= PClass

and I have python complaining about TypeError: __class__ assignment:
only for heap types...

It seems thus that my approach is not possible, but problem is that I
can not see another approach that would not involve far more efforts
that this one (I have the impression I have to forget about making my
PClass derived from _PClass, but instead embed a _PClass instance in
PClass, far from ideal cause I would have to reimplement all method, not
only those that I want to change :( )
This is particularly frustrating cause I also have the impression that
want I want to do was at one time possible in python, let say in
2002-2003, when __class__ was already assignable but before assignment
was forbidden for non-heap types

Any hint on this problem?

Thanks,

Greg.
Jul 18 '05 #1
6 3073
gregory lielens <gr************ *@fft.be> writes:
Hello,

I am currently writing python bindings to an existing C++ library, and
I just encountered a problem that I hope has been solved by more
experienced python programmers:

A C++ class (let's call it CClass) is binded using classical Python
extension API to _PClass, which is accesible through python without
any problem. The problem is that I want this class to be
extended/extensible in python, and expose the python-extended version
(PClass) to library users (_PClass should never be used directly nor
be retruned by any function).
The aim is to leave only performance critical methods in C++ so that
the binding work is minimal, and develop the other methods in python
so that they are easier to maintain/extend.

We thus have something like this

class PClass(_PClass) :
def overide_method( self,...):
...
def new_method(self ,...):
...

and I can define
a=PClass()
and use my new or overiden method
a.overide_metho d() a.new_method() as intended...

So far, so good, trouble begin when I have a method from another class
PClass2 derived from _PClass2 which bind the C++ class CClass2, that
should return objects of type PClass:

Let call this method troublesome_met hod:

b=_PClass2()
c=b.troublesome _method()
type(c) gives _PClass.

now I want to define a python class PClass2 for extending methods of
_PClass2 like I have done for _PClass, in particular I want that
PClass2 troublesome_met hod return objects of type PClass instead of
_PClass...

To this end I try something like this

class PClass2(_PClass 2):
...
def troubelsome_met hod(self):
base=_PClass2.t roublesome_meth od(self)
base.__class__= PClass

and I have python complaining about TypeError: __class__ assignment:
only for heap types...

It seems thus that my approach is not possible, but problem is that I
can not see another approach that would not involve far more efforts
that this one (I have the impression I have to forget about making my
PClass derived from _PClass, but instead embed a _PClass instance in
PClass, far from ideal cause I would have to reimplement all method,
not only those that I want to change :( )
This is particularly frustrating cause I also have the impression that
want I want to do was at one time possible in python, let say in
2002-2003, when __class__ was already assignable but before assignment
was forbidden for non-heap types

Any hint on this problem?

I have just run into the same thing with the builtin list type. The trick
was not to declare my subclass directly from list, but rather a subclass
of list. So try this:

class PClassBase(_PCl ass):
pass

class PClass(PClassBa se):
...

class PClass2(PClassB ase):
...

Why? I cannot say other than I have noted that Python new-style classes
and extension types are not quite the same thing. That is, a new-style
class is a particular kind of extension type.

Lenard Lindstrom
<le***@telus.ne t>
Jul 18 '05 #2
Thanks for your answer, it means I am not the only one having this kind
of problem...
I have just run into the same thing with the builtin list type. The trick
was not to declare my subclass directly from list, but rather a subclass
of list. So try this:

class PClassBase(_PCl ass):
pass

class PClass(PClassBa se):
...

class PClass2(PClassB ase):
...
I think here you mean PClass2(PClassB ase2), with a
PClassBase2(_PC lass2): In my example the 2 class do not inherit fro the
same base class... Why? I cannot say other than I have noted that Python new-style classes
and extension types are not quite the same thing. That is, a new-style
class is a particular kind of extension type.


I see how it can help me making PClassBase a PClass (or any type derived
from PClassBase), but what I fail to see is how this will allow me to
change a _PClass into one of it's derived types: this is necessary for
updating methods of _PClass2 that return object of type _PClass (and on
this I do not have much control, both _PClass and _PClass2 and all of
their methods are implemented in C++). To updates theses methods for the
pure python derived class PClass2, I have to make them return the python
class PClass instead of the original _PClass, which means I still have
to transform a _PClass object into its derived type PClassBase or
PClass, and at this time things go pear-shaped :-(....or is there
something I miss?

Greg.
Jul 18 '05 #3
gregory lielens <gr************ *@fft.be> writes:
Thanks for your answer, it means I am not the only one having this
kind of problem...
I have just run into the same thing with the builtin list type. The trick
was not to declare my subclass directly from list, but rather a subclass
of list. So try this:
class PClassBase(_PCl ass):
pass
class PClass(PClassBa se):
...
class PClass2(PClassB ase):
...

I think here you mean PClass2(PClassB ase2), with a
PClassBase2(_PC lass2): In my example the 2 class do not inherit fro
the same base class...
Why? I cannot say other than I have noted that Python new-style classes
and extension types are not quite the same thing. That is, a new-style
class is a particular kind of extension type.


I see how it can help me making PClassBase a PClass (or any type
derived from PClassBase), but what I fail to see is how this will
allow me to change a _PClass into one of it's derived types: this is
necessary for updating methods of _PClass2 that return object of type
_PClass (and on this I do not have much control, both _PClass and
_PClass2 and all of their methods are implemented in C++). To updates
theses methods for the pure python derived class PClass2, I have to
make them return the python class PClass instead of the original
_PClass, which means I still have to transform a _PClass object into
its derived type PClassBase or PClass, and at this time things go
pear-shaped :-(....or is there something I miss?

Sorry for the confusion. This looks like a situation best handled with
embedding rather than inheritance. The PClass and PClass2 wrapper classes
can share whatever relationship _PClass and _PClass2 share.

class PClass:
def __init__(inst=N one):
if inst is None:
inst = _PClass()
self._inst = inst
def override_method (self, ...):
self._inst.over ride_method(... )
def new_method(self , ...):
...

class PClass2:
self._inst = _PClass2()
def troublesome_met hod(self):
base = PClass(self._in st.troublesome_ method())
...
return base

Alternatively you could provide a way to pass PClass back to the extension module
for _PClass2.troubl esome_method to use instead of _PClass when creating a return
object. But the embedding approach seems more appropriate when _PClass is not to
be used directly.

Lenard Lindstrom
<le***@telus.ne t>
Jul 18 '05 #4
Sorry for the confusion. This looks like a situation best handled with
embedding rather than inheritance. The PClass and PClass2 wrapper classes
can share whatever relationship _PClass and _PClass2 share.

class PClass:
def __init__(inst=N one):
if inst is None:
inst = _PClass()
self._inst = inst
def override_method (self, ...):
self._inst.over ride_method(... )
def new_method(self , ...):
...

class PClass2:
self._inst = _PClass2()
def troublesome_met hod(self):
base = PClass(self._in st.troublesome_ method())
...
return base
Yes I was affraid this would be the conclusion: embedding instead of
inheritance...B ut this means that not only the method that need to be
modified need to be rewritten in python, all the other ones also just to
delegate to the embedded instance...
This is not too practical, even if such writing can be more or less
automatized...
For my purpose it seems that there was a big step backward between
python 2.2 and 2.3, and I am surprised this has been mostly
unnoticed...Thi s problem should be common for many people trying to
write mixed C/C++ / python classes. I found some reference on this in
the list archive, a few people beeing anoyed by it, but the proposition
to make the test about assignment to class less strict was not retained
it seems...I plan to experiment a little with the python C
implementation to see what happen if I bypass this test...
Alternatively you could provide a way to pass PClass back to the extension module
for _PClass2.troubl esome_method to use instead of _PClass when creating a return
object. But the embedding approach seems more appropriate when _PClass is not to
be used directly.


Yes but again this is not so practical, the purpose of the _PClass /
PClass implementation was to make the bindings as light, and as easy to
implement / extend as possible, and both the embedding and the creation
of PClass within _PClass2 methods defeat this purpose...

I think allowing assignment to class for native types should be done if
possible, for example if the new class is a derived type (possibly using
__slots__)... I saw a post on this by Guido, but the reason why it was
not possible is not clear to me and the thread died without further
explanations... Maybe my experiments will show me what happen, or someone
more knowledgeable than me can explain why this is not possible?

Greg.
Jul 18 '05 #5
gregory lielens <gr************ *@fft.be> writes:

(...)
Yes I was affraid this would be the conclusion: embedding instead of
inheritance...B ut this means that not only the method that need to be
modified need to be rewritten in python, all the other ones also just
to delegate to the embedded instance...
This is not too practical, even if such writing can be more or less
automatized...


Unless I'm misunderstandin g, couldn't one of __getattr__ or
__getattribute_ _ make mapping other methods you don't override very
simple and practical, not to mention fully automated with 2-3 lines of
code? In particular, __getattr__ would seem good for your use since
it is only called for attributes that couldn't already be located.

I've had code that wrapped underlying objects in a number of cases, and
always found that to be a pretty robust mechanism.

-- David
Jul 18 '05 #6
Unless I'm misunderstandin g, couldn't one of __getattr__ or
__getattribute_ _ make mapping other methods you don't override very
simple and practical, not to mention fully automated with 2-3 lines of
code? In particular, __getattr__ would seem good for your use since
it is only called for attributes that couldn't already be located.

I've had code that wrapped underlying objects in a number of cases, and
always found that to be a pretty robust mechanism.


Thanks for mentioning this, after more research I came up with something
usable, using delegating technique from python cookbook:
#wrapper

def wrap_class(base ):
class wrapper:
__base__=base
def __init__(self,* args,**kwargs):
if len(args)==1 and type(args[0])==self.__base_ _ and kwargs=={}:
self._base = args[0]
else:
self._base=self .__class__.__ba se__.__new__(se lf.__class__.__ base__,*args,** kwargs)
def __getattr__(sel f,s):
return self._base.__ge tattribute__(s)
return wrapper

#wrap class
complex2=wrap_c lass(complex)
#extend wrapper class
def supaprint(self) :
print "printed with supaprint(tm):"
print self
complex2.supapr int=supaprint

#define wrapper class from base class
c1=1+1j
c2=complex2(c1)
#test old functionalities
print c1==c2
print "c1=",c1
print "c2=",c1
#test extension
c2.supaprint()
c1.supaprint()

So this basically fit the bill, it even delegates special methods it
seems, although I am not sure why...It is like writting heritage ourself,
in a way :-)

Remaning problem is that if we use the class generating
wrapper function (simple), we loose the classic class definition syntax
and rely on explicitely adding methods.
The alternative is to include the wrapper
machinery in every "home-derived" class, but you are right, it is not as bad as I
though :-)

The biggest point I am not sure now is performance: Isn't a big penalty
associated to this embedding, compared to derivation? Python performance
is not so critical in our application, but I would be uncomfortable having
a factor 10 penalty in methd calling associated to this approach...For now, this will be used for
testing new implementations/extensions, that will be added to the C++
written binding afterwards.

I'd like to thanks the list for the hints, I will post the results of my
experimatations relaxing the assigment to __class__ test if they are
interesting.

Greg.

Jul 18 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

13
1515
by: Chris Cioffi | last post by:
Hello all! I'm trying to subclass int such that once it reaches a certain value, it flips back to the starting count. This is for use as an X12 control number. Subclassing int and getting the display like I want it was trivial, however what's the best way to make it such that: 990 + 1 = 991 991 + 1 = 992 .... 998 + 1 = 999
3
1558
by: Mizrandir | last post by:
I'd like to subclass numarray's array. I'd like to add some methods and override others like __init__. I don't know how to do this and haven't found help searching the manual or the web, can someone help? For example imagine I just want to do something as simple as making a subclass "NewClass" with the __init__ method overridden so that the behaviour would be: >>> a = NewClass(2) >>> print a
4
1790
by: harold fellermann | last post by:
Hi all, I have a problem pickling an extension class. As written in the Extending/Embedding Manual, I provided a function __reduce__ that returns the appropreate tuple. This seams to work fine, but I still cannot pickle because of the following error: >>> from model import hyper >>> g = hyper.PeriodicGrid(4,4,1)
166
8673
by: Graham | last post by:
This has to do with class variables and instances variables. Given the following: <code> class _class: var = 0 #rest of the class
5
2527
by: Barry Kelly | last post by:
I'm running this version of Python: Python 2.4.3 (#1, May 18 2006, 07:40:45) on cygwin I read in the documentation that these two expressions are interchangeable: x.__getattribute__('name') <==> x.name
4
6257
by: KraftDiner | last post by:
I have the following code... import array len32 = array.array('L') len16 = array.array('H') len32.append(0) len16.append(0) y = len32
3
4511
by: dgdev | last post by:
I would like to pickle an extension type (written in pyrex). I have it working thus far by defining three methods: class C: # for pickling __getstate__(self): ... # make 'state_obj' return state_obj __reduce__(self):
1
2426
by: gregory.lielens | last post by:
Hello, We are currently writing python bindings to an existing C++ library, and we encountered a problem that some of you may have solved (or that has found unsolvable :( ): A C++ class (let's call it CClass) is binded using classical Python extension API to _PClass, which is accesible through python without any
16
2077
by: manatlan | last post by:
I've got an instance of a class, ex : b=gtk.Button() I'd like to add methods and attributes to my instance "b". I know it's possible by hacking "b" with setattr() methods. But i'd like to do it with inheritance, a kind of "dynamic subclassing", without subclassing the class, only this instance "b" ! In fact, i've got my instance "b", and another class "MoreMethods"
0
9589
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9423
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
1
9999
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8876
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7413
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6675
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5310
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
3967
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3570
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.