0

I have a base class which has a __init__ that takes two parameters. I want to create a derived class object, given that I have a base class object. I want to do the following,

a_obj = A(10, 'f') 
## given that I have a_obj, create b_obj
b_obj = B(a_obj)

and get a result such that

type(b_obj) => B

print(b_obj.age) => 10
print(b_obj.sex) => "f"

I tried the following, where the __new__ of B would call A's __new__ and ask it to create an object of type B(an empty object). But at this point I dont know how to set B to have all the functionalities of A.

class A:
  def __init__(self, age, sex):
    self.age = age
    self.sex = sex

class B(A):
  def __new__(cls, a_obj):
    a_class = a_obj.__class__
    b_obj = a_class.__new__(cls)
    a_class.__init__(b_obj, a_obj) #doesnt work since A's init takes 2 params

Is there a better way than to typecast the given A's object to B? ( i.e a_obj.__classs__ = b_obj )

Edit: B is a dynamically created class(using type). So B wouldnt know beforehand what are the parameters that A's __init__ would take.

4 Answers 4

2

The simple way, by passing a's attributes in a call to super

class A:
  def __init__(self, age, sex):
      self.age = age
      self.sex = sex

class B(A):
    def __init__(self, a):
         """a is an instance of A"""
         super().__init__(a.age, a.sex)

In answer to "what if B was a dynamically generated class? B doesnt know what A's params are", that is a lot harder, and requires some true python hacking.

class B(A):
    def __init__(self, a):
        self.__dict__.update(a.__dict__)

I do not endorse doing this. It is bad coding practise and possibly error prone.

Sign up to request clarification or add additional context in comments.

1 Comment

Not hard at all actually and does not require any hack - just use *args and **kwargs like you would for a decorator or any generic callable.
1

Quite simply, pass a_object.age and a_object.sex to the parent constructor.

class A(object):
  def __init_(self, age, sex):
    self.age = age
    self.sex = sex

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

Now note that one usually expects subclasses to be compatible with their parents, which is not the case here.

Edit: to answer the additional question "what if B is dynamically generated and doesn't know beforehand what are the parameters that A's init would take", the canonical solution is to use varargs and keyword args:

class B(A):
    def __init__(self, *args, **kwargs):
        super(B, self).__init__(*args, **kawargs)

5 Comments

@FHTMitchell chill out - your answer wasn't posted when I started writing mine, I only saw it after posting (else I wouldn't have bothered answering).
Sorry. I'm chill +1
@FHTMitchell and bruno, what if B was a dynamically generated class? B doesnt know what A's params are.
@user2626431 use *args and **kwargs, cf my edited answer.
Your edit doesn't answer the question, I think: the __init__ of B is supposed to take only one parameter, and instance of a.
0

Well, with the example it's not clear whether inheritance will be used for any purpose other than a properties access. If getting all the object fields is only thing you want, I guess, it's not necessary to use inheritance.

Since every object in python has dict property, you can just copy it:

class A:
    def __init__(self, age, sex):
        self.age = age
        self.sex = sex

class B:
    def __init__(self, a_obj):
        self.__dict__ = a_obj.__dict__.copy()

if __name__ == "__main__":
    a_obj = A(10, "f")
    b_obj = B(a_obj)

    print(type(b_obj)) # B

    # Works as expected.
    print(b_obj.age)
    print(b_obj.sex)

Although provided example will work as-well with inheritance, but in that case I'd hardly suggest to use parent constructor as described above.

Comments

-2

Maybe using getattr, within class B,

class B:
    def __init__(self, a_object):
        self._a = a_object

    def __getattr__(self, item):
        return getattr(self._a, item)

So if b_obj doesn't have an age attribute, it will refer to the age within a_object.

1 Comment

The OP wants B to derive from A.

Your Answer

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.