8

I am quite new with python, is there a way to construct a child class using a parent instance?

Well I was thinking about:

class A:
  def __init__(self,a,b):
     self.a = a
     self.b = b         

class B(A):
  def __init__(self,A):
    self.super = A
    self.c = -1

  def __init__(self,a,b,c):
    super(a,b)
    self.c = c

myA = A(1,2)
myB = B(myA)

So for having B objects I could use A objects to construct them.

dijkstraman
  • 166
  • 2
  • 11
  • What do you mean *"using a parent instance"*? Are you trying to create an inheritance relationship (then just *use inheritance*) or a composition relationship (then of course `B` can have an attribute that is an `A` instance)? Could you give a non-trivial example that better represents what you are trying to do? – jonrsharpe Jul 23 '14 at 21:24
  • You may want to look into "roles" and "traits". – User Jul 23 '14 at 21:32
  • Do you want: a new instance, of type `B`, based on the existing `myA`? Or do you want to "upgrade" the existing `myA` to a `B`? – Jamie Cockburn Jul 23 '14 at 21:34
  • 1
    I am looking to have a new Instance of B constructed from myA(instance of A) – dijkstraman Jul 23 '14 at 21:36

3 Answers3

8

This will do what you ask, and create a new B, using the data from an existing A, and then complete the initialisation of the new B:

class A(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def __str__(self):
        return "A: a = %s, b = %s" % (self.a, self.b)

class B(A):
    def __init__(self, *args):
        if type(args[0]) is A:
            self.__dict__ = args[0].__dict__.copy()
            c = args[1]
        else:
            super(B, self).__init__(*args[:2])
            c = args[2]
        self.c = c

    def __str__(self):
        return "B: a = %s, b = %s, c = %s" % (self.a, self.b, self.c)

Usage:

myA = A(1, 2)
print myA
print B(3,4,5)   # regular B
myB = B(myA, 10) # B created from an A
print myB

Output:

A: a = 1, b = 2
B: a = 3, b = 4, c = 5
B: a = 1, b = 2, c = 10

Note that the new instance doesn't get a new copy of the data, it gets a new set of references to that data. If a were a list and you did myA.a.append(value), then myB.a would also have value in it. If you want that not to be the case, change the assignment of __dict__ to:

self.__dict__ = deepcopy(args[0].__dict__)

Note: None of this won't work if you're using slots, because __dict__ won't exist

Jamie Cockburn
  • 7,379
  • 1
  • 24
  • 37
  • 2
    Thanks for your answer, it looks like it is not that easy in python, in c++ this would the same as using the copyconstructor of parent class so I thought that I would be an intuitive way do it in python. – dijkstraman Jul 24 '14 at 10:05
0

You can make use of the facts that:

For example:

class A(object):
  pass

def CreateB(superclass):
  class subclass(superclass):
    pass
  return subclass

B = CreateB(A)
myA = A()
myB = B()

That said, it's not entirely clear to me what is the actual problem you are trying to solve.

Community
  • 1
  • 1
NPE
  • 486,780
  • 108
  • 951
  • 1,012
-1

In your example, methods in classes need a first argument to refer to themselves. Normally this is named self.

class A:
    pass #class A code

class B(A):
    def __init__(self, a):
       self.super = a

myA = A()
myB = B(myA)

The code above will create a B instance with a reference to an A instance called super. If you want B to inherit from A then you would change the code slightly more.

class A:
    pass #class A code

class B(A):
    def __init__(self):
        A.__init__(self)

myA = A()
myB = B()
Andrew Johnson
  • 3,078
  • 1
  • 18
  • 24