A proper (python 2.7) version of your code would be:
class A(object):
def __init__(self, firstname):
self.firstname = firstname
class B(A):
def __init__(self, lastname):
super(B, self).__init__(firstname)
self.lastname = lastname
parent = A('somefirstname')
child = B('somefirstname', 'somelastname')
print(child.firstname)
print(child.lastname)
But I suspect you don't really understand OO and specially not inheritance. In a comment you write:
I find it incredibly unproductive that I have to instantiate an instance of the parent class inside the child class.
Where have you seen this ??? The call to the superclass's __init__ is NOT "creating an instance of the parent class", it's just applying the parent's class __init__ on the current child instance. How else would the child instance be properly initialized ?
Is there really not a way to simply pass an instance of a parent to a child class and simply adding new attributes?
yes you can - just call the method on the class and pass the instance as first argument:
parent = A("firstname")
B.__init__(parent, "lastname")
print(parent.firstname, parent.lastname)
but this will NOT do what you expect - parent will remain an A instance (though with additional attributes):
print(type(parent))
Also, your B class is not compatible with A so it's not a proper subtype of A (according to liskov's substitution principle). This is not technically illegal, and not necessarily a problem, but inheritance is not only about implementation reuse, it's also about subtyping (inheritance denotes a is a relationship so "B inherits from A" means that "B is a (kind of) A"). Since implementation inheritance is mostly a restricted case composition/delegation, you may want to think twice about your models semantics before deciding between inheritance and composition/delegation.
EDIT - this:
class A(object):
def __init__(self, firstname):
self.firstname = firstname
class B(A):
def __init__(self, parent, lastname):
self.lastname = lastname
A.__init__(self, parent.firstname)
parent = A('somefirstname')
child = B(parent, 'somelastname')
is a very badly designed version of this:
class A(object):
def __init__(self, firstname):
self.firstname = firstname
class B(A):
def __init__(self, firstname, lastname):
super(B, self).__init__(firstname)
self.lastname = lastname
parent = A('somefirstname')
child = B(parent.firstname, 'somelastname')
And it's badly designed because it requires that you have an A instance -or anything having a "firstname" attribute - to create a B instance, when all B needs is the firstname. You always want to restrict coupling / dependencies between objects to the minimum required.
FWIW it also looks like you're confusing two different acceptations of "parent" and "child".
In OOP, "parent" and "child" are about classes, not instances, and do not imply any direct relationship between instances of the base and derived classes (note the use of "base" and "derived" instead of "parent" and "child" - this is less ambiguous).
Here it looks like you want to model some inter-instances relationships ("Luke, I'm your father" anyone ?) where "child" AS A "parent" (and not "is a"). Inheritance is not the proper tool here, you want composition/delegation instead:
class Father(object):
def __init__(self, firstname):
self.firstname = firstname
class Child(object):
def __init__(self, father, lastname):
self.father = father # composition
self.lastname = lastname
@property
def firstname(self):
# delegation
return self.father.firstname
vador = Father("Vador")
luke = Child(vador, "Luke")
AfromB,Bneeds to initializeAfully. For example,B.__init__()could accept bothfirstnameandlastname, then initialize the inheritedAstructure withfirstname(i.e.super(B, self).__init__(firstname)) and store thelastnameon top. The inheritance chain is linked automatically by Python so you don't need to provide aparentwhen initializing inherited objects.self.__firstnameunless you really understand what it does and what it's intended for - hint: the proper way to mark an attribute as "private"/"protected" is one single leading underscore and 2/ don't make an attribute protected for no good reason - you can always turn it into a computed attribute later if needed.