In Python, think of variable names (like self) as "pointing at" or "referencing" values. When you make an instance of B:
b = B(2)
The B.__init__ method is called with the variable self already assigned to the inchoate instance of B. Now, inside this method, when Python reaches
self = A(x)
the variable self gets reassigned to a new instance of A. The instance of B still exists; self just no longer points to it.
Note that self is a variable like any other in Python. (self is not a keyword, it is only a convention that the first argument to methods is called self.)
By the way, to initialize self with the value of x, use
class B(A):
def __init__(self,x):
A.__init__(self, x) # <-- Note the x
print "constructing B"
self.printx()
Then
b = B(2)
b.printx()
yields
constructing A
constructing B
x = 2
x = 2
When a class has an alternate constructor, such as getA, a typical pattern in Python is to use a classmethod:
class A(object):
def __init__(self, x=0):
print "constructing A"
self.x = x
def printx(self):
print "x =",self.x
@classmethod
def getA(cls, x):
print('constructing getA')
self = cls(x)
self.y = 1
return self
Now to make an instance of A with the classmethod getA, you'd say
a = A.getA(x)
The class A is passed as the first argument to the classmethod getA, and stored in the variable cls.
What is beautiful about doing it this way (instead of using a factory function getA), is that if you subclass A like this:
class B(A):
def __init__(self,x):
A.__init__(self, x)
print "constructing B"
self.printx()
then you can make instances of B using the getA classmethod as well:
b = B.getA(2)
yields
constructing getA
constructing A
constructing B
x = 2
and
print(type(b))
print(b.y)
yields
<class '__main__.B'> # b is an instance of B
1 # showing the y attribute has been set.