Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > overriding method that returns base class object

Reply
Thread Tools

overriding method that returns base class object

 
 
Stuart McGraw
Guest
Posts: n/a
 
      02-16-2004
I have a class A from a third party that I cannot change
and is implemented in C. I derive my own class B from A
and add a couple new methods and override a method. The
problem is that A has a method (call it A.f() ) that creates
and returns a new A object. I need B.f() to return a B
object derived from A.f(). What is the best way to make
that happen?

 
Reply With Quote
 
 
 
 
Peter Hansen
Guest
Posts: n/a
 
      02-16-2004
Stuart McGraw wrote:
>
> I have a class A from a third party that I cannot change
> and is implemented in C. I derive my own class B from A
> and add a couple new methods and override a method. The
> problem is that A has a method (call it A.f() ) that creates
> and returns a new A object. I need B.f() to return a B
> object derived from A.f(). What is the best way to make
> that happen?


If I understand this correctly, it has nothing to do with the
fact that the parent class is implemented in C and you just
need to know a little uncommon syntax:

class A:
def f(self):
return A()

class B(A):
def f(self):
obj = A.f(self)
# do whatever you want to obj here
return obj

The key is what you mean by "a B object derived from A.f()". If
by derived you mean something to do with _inheritance_, then
either you don't understand inheritance or you weren't clear what
you wanted.

If you just mean you want B's f() to do something special to the
A object that A.f() returns, then the above code should let you
do that properly...

-Peter
 
Reply With Quote
 
 
 
 
Stuart McGraw
Guest
Posts: n/a
 
      02-16-2004
Sorry, you are right, I wasn't clear. I mean B inherits from
A. Here is what I am trying to do...

Class A has a method A.a() that returns an A. I want a
identical class but with an additional property .newprop
and method .b() And I want .a() to return a B, not an A.

class B (A):
def __init__(self, *args, **kwds):
A.__init__(self, *args, **kwds)
self.newprop = 99
def a(self):
x = A.a(self) # x is an A
x.__class__ = B
return x # I want x to be a B, i.e have b() and .newprop.
def b(self):
...something...

Yes, I know this is bogus. But I am not sure what
I should be doing. And to correct what I originally
posted, A is implented in python (but I still can't
change it for administrative reasons), but it's properties
are declared with "__slots__ = [...]" if that makes a
difference. This is all in Python 2.3.3.


"Peter Hansen" <(E-Mail Removed)> wrote in message news:(E-Mail Removed)...
> Stuart McGraw wrote:
> >
> > I have a class A from a third party that I cannot change
> > and is implemented in C. I derive my own class B from A
> > and add a couple new methods and override a method. The
> > problem is that A has a method (call it A.f() ) that creates
> > and returns a new A object. I need B.f() to return a B
> > object derived from A.f(). What is the best way to make
> > that happen?

>
> If I understand this correctly, it has nothing to do with the
> fact that the parent class is implemented in C and you just
> need to know a little uncommon syntax:
>
> class A:
> def f(self):
> return A()
> se
> class B(A):
> def f(self):
> obj = A.f(self)
> # do whatever you want to obj here
> return obj
>
> The key is what you mean by "a B object derived from A.f()". If
> by derived you mean something to do with _inheritance_, then
> either you don't understand inheritance or you weren't clear what
> you wanted.
>
> If you just mean you want B's f() to do something special to the
> A object that A.f() returns, then the above code should let you
> do that properly...
>
> -Peter

 
Reply With Quote
 
Aahz
Guest
Posts: n/a
 
      02-17-2004
In article <40315037$0$199$(E-Mail Removed)>,
Stuart McGraw <(E-Mail Removed)> wrote:
>
>Class A has a method A.a() that returns an A. I want a
>identical class but with an additional property .newprop
>and method .b() And I want .a() to return a B, not an A.
>
> class B (A):
> def __init__(self, *args, **kwds):
> A.__init__(self, *args, **kwds)
> self.newprop = 99
> def a(self):
> x = A.a(self) # x is an A
> x.__class__ = B
> return x # I want x to be a B, i.e have b() and .newprop.
> def b(self):
> ...something...
>
>Yes, I know this is bogus. But I am not sure what I should be doing.
>And to correct what I originally posted, A is implented in python
>(but I still can't change it for administrative reasons), but it's
>properties are declared with "__slots__ = [...]" if that makes a
>difference. This is all in Python 2.3.3.


class A:
def a(self):
return self.__class__()
--
Aahz ((E-Mail Removed)) <*> http://www.pythoncraft.com/

"Argue for your limitations, and sure enough they're yours." --Richard Bach
 
Reply With Quote
 
Scott David Daniels
Guest
Posts: n/a
 
      02-17-2004
Stuart McGraw wrote:

> Sorry, you are right, I wasn't clear. I mean B inherits from
> A. Here is what I am trying to do...
>
> Class A has a method A.a() that returns an A. I want a
> identical class but with an additional property .newprop
> and method .b() And I want .a() to return a B, not an A.
>
> class B (A):
> def __init__(self, *args, **kwds):
> A.__init__(self, *args, **kwds)
> self.newprop = 99
> def a(self):
> x = A.a(self) # x is an A
> x.__class__ = B
> return x # I want x to be a B, i.e have b() and .newprop.
> def b(self):
> ...something...
>
> Yes, I know this is bogus. But I am not sure what
> I should be doing.

Typically, you might want to do something like:

class B(A):
...
def a(self):
x = self.__class__.__new__(self.__class__,...)
# __new__ Usually gets no more args here, but

x.__init__(...)
# And here is where we do the actual init

...

Hope this helps

-Scott David Daniels
http://www.velocityreviews.com/forums/(E-Mail Removed)
 
Reply With Quote
 
Paul McGuire
Guest
Posts: n/a
 
      02-17-2004
"Aahz" <(E-Mail Removed)> wrote in message
news:c0rmod$gso$(E-Mail Removed)...
<snip>
>
> class A:
> def a(self):
> return self.__class__()
> --

OP can't do this, can't get at source code of A.

Assuming that you don't want to write __init__() to take an A argument, you
need something like:

class B(A):
def makeFromAnA(other): # other is an A instance
# construct a B - could pass initialization args from
# other if this is part of the interface
newB = B()

# ... copy base class A fields from other to newB here ...

# ... add B-ish stuff to newB here ...

return newB
makeFromAnA=staticmethod(makeFromAnA)

def a(self):
return B.makeFromAnA( A.a() )

Here's an example:
import random
class Point2D(object): # pretend this is implemented in C, so we can't
change the code
def __init__(self,xval,yval):
self.x = xval
self.y = yval
def randomPoint():
return Point2D( random.random()*100, random.random()*100 )
randomPoint=staticmethod(randomPoint)

class Point3D(Point2D): # not really good O-O design, but that's not the,
um, point
def __init__(self,xval,yval,zval):
self.x = xval
self.y = yval
self.z = zval
def make3DPtFrom2DPt(other):
print "Make 3D pt from",other
return Point3D(other.x,other.y,0)
# or if the __init__'s are not similar,
# manually assign fields
newPt3D = Point3D(0,0,0)
newPt3D.x = other.x
newPt3D.y = other.y
return newPt3D
make3DPtFrom2DPt=staticmethod(make3DPtFrom2DPt)
def randomPoint():
newPt = Point3D.make3DPtFrom2DPt( Point2D.randomPoint() )
newPt.z = random.random()*100
return newPt
randomPoint=staticmethod(randomPoint)

print Point2D.randomPoint()
print Point3D.randomPoint()

-- Paul


 
Reply With Quote
 
John Roth
Guest
Posts: n/a
 
      02-17-2004

"Stuart McGraw" <(E-Mail Removed)> wrote in message
news:40315037$0$199$(E-Mail Removed)...
> Sorry, you are right, I wasn't clear. I mean B inherits from
> A. Here is what I am trying to do...
>
> Class A has a method A.a() that returns an A. I want a
> identical class but with an additional property .newprop
> and method .b() And I want .a() to return a B, not an A.
>
> class B (A):
> def __init__(self, *args, **kwds):
> A.__init__(self, *args, **kwds)
> self.newprop = 99
> def a(self):
> x = A.a(self) # x is an A
> x.__class__ = B
> return x # I want x to be a B, i.e have b() and .newprop.
> def b(self):
> ...something...
>
> Yes, I know this is bogus. But I am not sure what
> I should be doing. And to correct what I originally
> posted, A is implented in python (but I still can't
> change it for administrative reasons), but it's properties
> are declared with "__slots__ = [...]" if that makes a
> difference. This is all in Python 2.3.3.


What's bogus about it? You can change the
class of an instance to be anything you want.
The only issue might be the slots; I'm not all
that familiar with what restrictions they might
impose.

Granted, there are relatively few cases
where changing the class of an instance on
the fly is actually better than the alternatives,
but this might be one of them.

John Roth

>
>
> "Peter Hansen" <(E-Mail Removed)> wrote in message

news:(E-Mail Removed)...
> > Stuart McGraw wrote:
> > >
> > > I have a class A from a third party that I cannot change
> > > and is implemented in C. I derive my own class B from A
> > > and add a couple new methods and override a method. The
> > > problem is that A has a method (call it A.f() ) that creates
> > > and returns a new A object. I need B.f() to return a B
> > > object derived from A.f(). What is the best way to make
> > > that happen?

> >
> > If I understand this correctly, it has nothing to do with the
> > fact that the parent class is implemented in C and you just
> > need to know a little uncommon syntax:
> >
> > class A:
> > def f(self):
> > return A()
> > se
> > class B(A):
> > def f(self):
> > obj = A.f(self)
> > # do whatever you want to obj here
> > return obj
> >
> > The key is what you mean by "a B object derived from A.f()". If
> > by derived you mean something to do with _inheritance_, then
> > either you don't understand inheritance or you weren't clear what
> > you wanted.
> >
> > If you just mean you want B's f() to do something special to the
> > A object that A.f() returns, then the above code should let you
> > do that properly...
> >
> > -Peter



 
Reply With Quote
 
Paul Rubin
Guest
Posts: n/a
 
      02-17-2004
"Stuart McGraw" <(E-Mail Removed)> writes:
> Class A has a method A.a() that returns an A. I want a
> identical class but with an additional property .newprop
> and method .b() And I want .a() to return a B, not an A.
>
> class B (A):
> def __init__(self, *args, **kwds):
> A.__init__(self, *args, **kwds)
> self.newprop = 99
> def a(self):
> x = A.a(self) # x is an A
> x.__class__ = B
> return x # I want x to be a B, i.e have b() and .newprop.


Ugh!!

> Yes, I know this is bogus. But I am not sure what I should be doing.


I think you have to make B into a container for an A. Something like:

class B(A):
def __init__(self, *args, **kwds):
self.newprop = 99
self.wrapped_A = A(*args, **kwds)
def a(self):
x = B()
x.wrapped_A = A.a(self.wrapped_A)
return # I want x to be a B, i.e have b() and .newprop.
def __getattr__(self, attr):
# delegate all inherited operations to the wrapped A object
return A.__getattr__(self.wrapped_A, attr)

You might also be able to do something crazy, like change A's metaclass
so that its __new__ operation can make a B under certain circumstances.
 
Reply With Quote
 
Stuart McGraw
Guest
Posts: n/a
 
      02-17-2004

"Scott David Daniels" <(E-Mail Removed)> wrote in message news:40316850$(E-Mail Removed)...
> Stuart McGraw wrote:
>
> > Sorry, you are right, I wasn't clear. I mean B inherits from
> > A. Here is what I am trying to do...
> >
> > Class A has a method A.a() that returns an A. I want a
> > identical class but with an additional property .newprop
> > and method .b() And I want .a() to return a B, not an A.
> >
> > class B (A):
> > def __init__(self, *args, **kwds):
> > A.__init__(self, *args, **kwds)
> > self.newprop = 99
> > def a(self):
> > x = A.a(self) # x is an A
> > x.__class__ = B
> > return x # I want x to be a B, i.e have b() and .newprop.
> > def b(self):
> > ...something...
> >
> > Yes, I know this is bogus. But I am not sure what
> > I should be doing.

> Typically, you might want to do something like:
>
> class B(A):
> ...
> def a(self):
> x = self.__class__.__new__(self.__class__,...)
> # __new__ Usually gets no more args here, but
>
> x.__init__(...)
> # And here is where we do the actual init


I don't think this will work. A.a() returns an A, but one that
is initialized differently than an A() instance. That is, A.a()
does more that just __new__() and __init__() to it. So if I
do the above, I end up with a subtype (right word?) of an
A(), not an A.a().

Now I think that my B.a() must call A.a() and somehow
dynamically change the type of the object received? As suggesed
above, I tried to change the class (x.__class__ = B) but that
just results in an exception
TypeError: __class__ assignment: 'B' object layout differs from 'A'

Or maybe what I am trying to do is not possible in Python?

 
Reply With Quote
 
Stuart McGraw
Guest
Posts: n/a
 
      02-17-2004
"Paul Rubin" <http://(E-Mail Removed)> rote in message news:(E-Mail Removed)...
> "Stuart McGraw" <(E-Mail Removed)> writes:
> > Class A has a method A.a() that returns an A. I want a
> > identical class but with an additional property .newprop
> > and method .b() And I want .a() to return a B, not an A.
> >
> > class B (A):
> > def __init__(self, *args, **kwds):
> > A.__init__(self, *args, **kwds)
> > self.newprop = 99
> > def a(self):
> > x = A.a(self) # x is an A
> > x.__class__ = B
> > return x # I want x to be a B, i.e have b() and .newprop.

>
> Ugh!!
>
> > Yes, I know this is bogus. But I am not sure what I should be doing.

>
> I think you have to make B into a container for an A. Something like:
>
> class B(A):
> def __init__(self, *args, **kwds):
> self.newprop = 99
> self.wrapped_A = A(*args, **kwds)
> def a(self):
> x = B()
> x.wrapped_A = A.a(self.wrapped_A)
> return # I want x to be a B, i.e have b() and .newprop.
> def __getattr__(self, attr):
> # delegate all inherited operations to the wrapped A object
> return A.__getattr__(self.wrapped_A, attr)
>
> You might also be able to do something crazy, like change A's metaclass
> so that its __new__ operation can make a B under certain circumstances.


Ahhhh.... I did not know about delegation. I do now, thanks.
A minor disadvantage is that, because I also delegate __setattr__
all the instance variable have to be assigned in the form
self.__dict__['var'], rather than self.var (as I discovered the hard
way). Ugly, but I can live with it. Thanks again.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
problem in running a basic code in python 3.3.0 that includes HTML file Satabdi Mukherjee Python 1 04-04-2013 07:48 PM
Problem with method overriding from base class Python 2 03-31-2008 08:37 PM
Overriding a class method with an object method Koszalek Opalek Perl Misc 8 07-06-2007 08:59 AM
Object creation - Do we really need to create a parent for a derieved object - can't the base object just point to an already created base object jon wayne C++ 9 09-22-2005 02:06 AM
Base class method that returns a pointer to a derived class? Teis Draiby C++ 3 04-02-2004 12:59 PM



Advertisments