3

I have a function which return instances of the class Parent:

def generateParent():
 do_stuff
 return Parent(some_parameters)

Now I want to init a subclass of Parent with the results of a call to generateParent():

class Child(Parent):
 def __new__():
 return generateParent(some_other_parameters) 

The problem is, when I override some methods from Parent in Child and then call them in instances of Child in my program, the original Parent method gets called instead of the new one from Child. Am I doing something wrong here? Am I using the correct design here for my task?

EDIT: I don't have access neither to Parent nor generateParent()

Solution(thanks to @Paul McGuire's answer):

class Child(object):
 def __init__(self):
 self.obj = generateParent()
 def __getattr__(self, attr):
 return getattr(self.obj, attr)
asked Jan 6, 2013 at 0:00
2
  • 4
    You are, on purpose, not returning a child from the constructor, but a parent, and then you are surprised that it acts like a parent? Commented Jan 6, 2013 at 0:02
  • I get it, how can I then extend a class but also init it with instances of the parent returned by a function? Commented Jan 6, 2013 at 0:11

3 Answers 3

5

Since generateParent is not your code, then instead of inheritance, you might want to use containment and delegation. That is, instead of defining a subclass, define a wrapper class that contains the generated object, forwards method calls to it when needed, but can add new behavior or modified behavior in the wrapper.

In this question, the OP had a similar situation, having a class generated in a libary, but wanting to extend the class and/or modify some behavior of the class. Look at how I added a wrapper class in that question, and you might consider doing something similar here.

answered Jan 6, 2013 at 0:41
Sign up to request clarification or add additional context in comments.

3 Comments

I tried your solution and this doesn't work at all for me, I tried to call any method of the Child object and always the Parent method gets called.
This solution is your best bet. If you had difficulty with it, post details of the code.
Ok, this is the best solution, I had an error testing the code.
1

Here's one way to do it:

def generateChild(params):
 p = generateParent(params)
 p.__class__ = Child
 return p
class Child(Parent):
 # put method overrides etc here
childinstance = generateChild(some_params)
Marcin
50.1k18 gold badges137 silver badges207 bronze badges
answered Jan 6, 2013 at 0:09

5 Comments

Using this, how would I go creating and using Child objects? Do I always have to call generateChild() before?
You could put those two lines (p = generateParent(params); p.__class__ = Child) in the __new__ method of Child.
@DavidRobinson I find your suggestion more 'pythonic' as I can create objects with new_child = Child()
I've used this technique myself, but you really need to be careful with it. Note that Child.__init__ will never be called in this case, and any instance variables defined in Child.__init__will not be created, which could cause problems in methods in Child that depend on them. If you do this, write Child.__init__ to call a method like Child.addChildAttributes() that would add any special attributes, then in generateChild(), after setting p.__class__, then call p.addChildAttributes().
Yep I am getting errors with this solution as init (from Parent?) is getting called with my init parameters and I haven't defined(or need to) any init.
1
  1. Perhaps you want generateParent to be able to make instances of other classes:

    def generateParent(cls=Parent):
     do_stuff
     return cls(some_parameters)
    

    Now this will make a Child object:

    child = generateParent(Child)
    
  2. Or perhaps you want Parent and all of its derived classes to use common initialization code?

    class Parent(object):
     def __init__(self):
     do_stuff
     # init from some_parameters
    class Child(Parent):
     # blah..
    
  3. Make your Child object able to copy information from a created Parent object:

    class Child(Parent):
     def __init__(self):
     model_parent = generateParent()
     self.a = model_parent.a
     self.b = model_parent.b
     # etc.
    
answered Jan 6, 2013 at 0:50

6 Comments

interesting approach, unfortunately as I commented to a now deleted answer I don't have access to the generateParent function.
hmm, maybe update the question to include this important bit of information?
sorry, I have added this info
Regarding 1. and 2. I dont have access to neither generateParent() nor Parent, and 3. I would have to copy a lot of properties from modelParent.
@elyase: can you provide details of how you want Child to differ from Parent? There are other possibilities, but it's hard to recommend something specific without details.
|

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.