0

I have two classes: a base class A and the derived class B. In the constructor of B I tried to use the constructor of A to initialize the instance. Why assignment "self = A(x)" in constructor of the derived class does not work?

class A:
    def __init__(self, x=0):
        print "constructing A"
        self.x = x

    def printx(self):
        print "x =",self.x 

class B(A):
    def __init__(self,x):
        A.__init__(self)
        print "constructing B"
        self = A(x)
        self.printx()


b = B(2)
b.printx()

The output:

constructing A
constructing B
constructing A
x = 2
x = 0
1
  • 1
    what exactly are you trying to do? ie, what is your expected output? Commented Nov 21, 2012 at 22:03

2 Answers 2

2

You don't want to call the constructor in B.__init__, and you should pass x to A.__init__

class A:
    def __init__(self, x=0):
        print "constructing A"
        self.x = x
    def printx(self):
        print "x =",self.x 

class B(A):
    def __init__(self,x):
        A.__init__(self, x)
        print "constructing B"
        self.printx()
Sign up to request clarification or add additional context in comments.

Comments

1

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.

2 Comments

Thank you @unutbu and @jfaller! So - how can I assign a value to 'self' without it getting reassigned to a new instance of A? The reason I ask is that I have a 'factory' function getA(x) that returns an object of type A. Is there any way I can use something like self = getA(x) in the constructor of B?
Don't try to reassign self. Instead think of ways to modify self (change its attributes). I've edited my post to show one way to do it.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.