By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,996 Members | 1,343 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,996 IT Pros & Developers. It's quick & easy.

overriding method that returns base class object

P: n/a
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?

Jul 18 '05 #1
Share this Question
Share on Google+
10 Replies


P: n/a
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
Jul 18 '05 #2

P: n/a
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" <pe***@engcorp.com> wrote in message news:40***************@engcorp.com...
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

Jul 18 '05 #3

P: n/a
In article <40*********************@news.frii.net>,
Stuart McGraw <sm******@frii.RemoveThisToReply.com> 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 (aa**@pythoncraft.com) <*> http://www.pythoncraft.com/

"Argue for your limitations, and sure enough they're yours." --Richard Bach
Jul 18 '05 #4

P: n/a
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
Sc***********@Acm.Org
Jul 18 '05 #5

P: n/a
"Aahz" <aa**@pythoncraft.com> wrote in message
news:c0**********@panix3.panix.com...
<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
Jul 18 '05 #6

P: n/a

"Stuart McGraw" <sm******@frii.RemoveThisToReply.com> wrote in message
news:40*********************@news.frii.net...
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" <pe***@engcorp.com> wrote in message

news:40***************@engcorp.com...
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

Jul 18 '05 #7

P: n/a
"Stuart McGraw" <sm******@frii.RemoveThisToReply.com> 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.
Jul 18 '05 #8

P: n/a

"Scott David Daniels" <Sc***********@Acm.Org> wrote in message news:40********@nntp0.pdx.net...
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?

Jul 18 '05 #9

P: n/a
"Paul Rubin" <http://ph****@NOSPAM.invalid> rote in message news:7x************@ruckus.brouhaha.com...
"Stuart McGraw" <sm******@frii.RemoveThisToReply.com> 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.
Jul 18 '05 #10

P: n/a
Stuart McGraw wrote:
"Paul Rubin" <http://ph****@NOSPAM.invalid> rote in message news:7x************@ruckus.brouhaha.com...
...
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.


If you can separate the names, you can do something like:

class B(object):
def __init__(self, *args, **kwargs):
self._a = A(*args, **kwargs)
self.newprop = 99
def __setattr__(self, name, val):
if name.startswith('_') or name == 'newprop':
self.__dict__[name] = val
else:
setattr(self._a, name, val)
def getattr(self, name):
return getattr(self._a, name)

--
-Scott David Daniels
Sc***********@Acm.Org
Jul 18 '05 #11

This discussion thread is closed

Replies have been disabled for this discussion.