Bob
Bob

Reputation: 1

Instance of a class in python

In the below code Class B inherits from Class A, and the variables of Class A are assigned through Class B. I have created two new instances of Class B using Check1 and Check2 as shown below:

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

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

    def printB(self):
        print("B = "+str(ClassA.A + ClassA.B))



if __name__ == '__main__':
    print('#### Part I - using Check1 ######')
    Check1 = ClassB(1,2)
    Check1.printB()
    print('#### Part II -  Using Check2 ######')
    Check2 = ClassB(5,6)
    Check2.printB()
    print('#### Part III -  Again Using Check1 ######')
    Check1.printB()

I get the following output:

#### Part I - using Check1 ######
B = 3
#### Part II -  Using Check2 ######
B = 11
#### Part III -  Again Using Check1 ######
B = 11

My question is why do I get B=11 when calling the Check1 in Part III ? Shouldn't python be creating a new instance of even the parent class for Check1 object, and shouldn't Check1 display the output as B=3 ?

How can I modify the above code so that Check1 can have value as B=3 when I call it in Part III?

Upvotes: 0

Views: 249

Answers (3)

NotAName
NotAName

Reputation: 4322

What you are trying to do in ClassB's __init__ method, super() can do for you (also what you're doing is not correct as others have pointed out). This way you don't have to repeat code and can initialise attributes only in the base class:

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

class ClassB(ClassA):
    def __init__(self, a, b):
        super().__init__(a=a, b=b)

    def printB(self):
        print("B = "+str(self.A + self.B))  

And the output:

Check1 = ClassB(1,2)
Check1.printB()
B = 3

Check2 = ClassB(5,6)
Check2.printB()
B = 11

Check1.printB()
B = 3

Upvotes: 0

user2357112
user2357112

Reputation: 280227

You seem to be under the impression that a Python object has separate instance variable namespaces for each of its classes, or that Python objects have C++-style base class subobjects. That's not how Python works.

When you create an instance of ClassB, you're only making one object, which is an instance of both ClassA and ClassB. There's no separate ClassA instance. When your ClassB.__init__ does

ClassA.A = a
ClassA.B = b

that doesn't mean "set the instance variables declared in ClassA", or "set the instance variables on some instance of ClassA attached to this object". This line assigns to class variables on ClassA, not instance variables on any object. (Also, you never delegated to the superclass constructor, so ClassA.__init__ gets skipped entirely.)

Class variables are global state - separate instances don't get separate copies. Creating Check2 overwrites the values set when creating Check1.


It looks like the behavior you want from ClassB's constructor is exactly the behavior of ClassA's constructor, so you can just inherit __init__. You don't need to write a separate __init__.

As for printB, that needs to access instance variables:

class ClassB(ClassA):
    def printB(self):
        print("B = "+str(self.A + self.B))

Upvotes: 1

Samwise
Samwise

Reputation: 71424

You're not implementing inheritance correctly -- assigning to ClassA's members overwrites the class object iself, not the inherited instance attributes (which are still accessed via self). In addition, you don't want to copy and paste the parent constructor; instead you should just call it directly.

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

   
class ClassB(ClassA):
    def __init__(self, a, b):
        ClassA.__init__(self, a, b)

    def printB(self):
        print("B = "+str(self.A + self.B))

Upvotes: 1

Related Questions