2

I am working on the class which prints different messages in english. I want to create another class with exactly the same functionality, but with messages in different language.

As I learned sth about subclasses recently I wanted to get some practice and rewrote my Class() methods to have all messages saved in variables, which I tried to override in NewClass(Class). Here is the shortcut of my code:

class Class:
    def __init__(self, some_other_arguments):
        self.msg_1 = 'message 1'
        if some_condition:
            raise KeyError(self.msg_1)

class NewClass(Class):
    def __init__(self, some_other_arguments):
        super().__init__(some_other_arguments)
        self.msg_1 = 'message 2'

object_1 = Class(some_arguments) #should print 'message 1'
#prints 'message 1'
object_2 = NewClass(some_argiments) #should print 'message 2'
#prints 'message 1'

At first I wanted to copy first class, rename it and change the messages. But this will produce redundant code which I would like to avoid. What am I doing wrong?

class Class:
  def __init__(self):
    self.msg_1 = 'message 1'
    print(self.msg_1)

class NewClass(Class):
  def __init__(self):
    super().__init__()
    self.msg_1 = 'message 2'

object_1 = Class() #prints 'message 1'
object_2 = NewClass() #prints 'message 1'
  • 2
    code works correctly for me. Maybe you have something wrong in different part of code. Create minimal working code with your problem which we could copy and run to see problem. – furas Sep 13 '19 at 01:23
  • 1
    Try to provide code that actually reproduces the problem, this code doesn't (although it had some formatting problems). Odds are you either solve the problem while trying to reproduce it, or you can share some code that allows us to reproduce it and point out the problem.' – Grismar Sep 13 '19 at 01:32
  • 2
    `super().__init__()` calls the `__init__` method of the superclass. So if you have the `print` statement inside your class constructor, it will be called before you overwrite `self.msg_1`. – Henry Yik Sep 13 '19 at 01:53
  • The question wording is a little misleading. `msg_1` would be better described as an instance variable, not a class variable. – RVS Jul 20 '22 at 21:28

2 Answers2

4

Your code seems to be working as intended on my end:

class Class:
    def __init__(self):
        self.msg_1 = 'message 1'

class NewClass(Class):
    def __init__(self):
    super().__init__()
        self.msg_1 = 'message 2'

object_1 = Class()
object_2 = NewClass()

object_1.msg_1 prints message 1

object_2.msg_1 prints message 2

EDIT

class Class:
    def __init__(self):
      self.msg_1 = 'message 1'
      print(self.msg_1)

class NewClass(Class):
    def __init__(self):
      super().__init__()
      self.msg_1 = 'message 2'
      print(self.msg_1)

The above code will print out:

message 1
message 1
message 2

So perhaps you can add in the message to the init call:

class Class:
    def __init__(self, message):
      self.msg_1 = message
      print(self.msg_1)

class NewClass(Class):
    def __init__(self, message):
      super().__init__(message)

Class('Hi')
NewClass('Bonjour')
PeptideWitch
  • 2,239
  • 14
  • 30
  • Take a look at my edit - is this what you have? Or something similar maybe. It shouldn't be giving you an error printing out the self variable after you declare it – PeptideWitch Sep 13 '19 at 01:49
  • Yes! That's the problem. Is there any way I could override the print() effect just by changing my self variables? Or maybe there is a better way to provide messages in another language. – Adam Malczewski Sep 13 '19 at 01:59
  • As Henry Yik pointed out, the `super().__init__()` call will run everything inside the first class, including the original message 1 print. What might be good is to pass the message into the `init` call itself – PeptideWitch Sep 13 '19 at 02:01
  • Got it, thanks! I would like to avoid messages as class arguments too (there are a lot of them and that could be little inconvenient). I am trying to make an application which enables to create a RPG character card step-by-step, with an option to choose the language. The Class (character statistics) would be used by my console app (during the RPG session), but it should be also usable separately as a single tool to just draw the statistics. As I can't override the print statements I thought about typing msg_x variables in separated files (en and pl) and import the one I need. Hope it will do. – Adam Malczewski Sep 13 '19 at 10:33
2

I used super(ChildClass, self).__init__() to call the constructor of the ParentClass. Althought, the documentation of super() shows that super().__init() is equivalent. Reference

Technically, you are doing the same. And so, it should be fine.

class A(object):
    def __init__(self):
        print("world")
        self.var = 'message 1'

class B(A):
    def __init__(self):
        print("hello")
        super(B, self).__init__()
        print('Before Changing: {}'.format(self.var))
        self.var = 'message 2'
        print('After Changing: {}'.format(self.var))

b = B()

Output

hello
world
Before Changing: message 1
After Changing: message 2

Your Code

You were getting 'message 1' printed out both times as it was only being printed from inside Class. But, if you include another print statement after changing msg_1 to 'message 2', that would solve your problem. I have added a few print statements to help tracking when the super is being called and what happens afterwards.

class Class:
    def __init__(self):
        print("Class")
        self.msg_1 = 'message 1'
        print(self.msg_1)

class NewClass(Class):
    def __init__(self):
        print("NewClass")
        super(NewClass, self).__init__()
        self.msg_1 = 'message 2'
        print("======")
        print(self.msg_1)  ### YOU NEEDED A PRINT STATEMENT HERE

object_1 = Class() #prints 'message 1'
print("==================")
object_2 = NewClass() #prints 'message 1' and then 'message 2'

Output

Class
message 1
==================
NewClass
Class
message 1
======
message 2

I hope this helps.

CypherX
  • 7,019
  • 3
  • 25
  • 37