0

please consider the following code:

class A:
    a = "a"

    def print_a(self):
        print("A says:", self.a)

    def print_warning_a(self):
        print("A says:", "Warning! B wrote something!")


class B:
    b = "b"

    def print_a(self):
        print("B says:", self.b)

    def print_warning_b(self):
        print("B says:", "Warning! A wrote something!") 

if __name__=="__main__":    
    class_a = A()
    class_b = B()

    class_a.print_a()
    class_b.print_b()

I would like the output to be something like:

>> A says: a
>> B says: Warning! A wrote something!
>> B says: b
>> A says: Warning! B wrote something!

In other words: I have theese two classes (A and B). I would like to call a method of class A whenever another method of class B is called. Also, I would like to call a method of class B whenever another method of class A is called, assuming this would not cause an infinite loop (as in the example above).

In this case I would like to call print_warning_a() when print_b() of class B fires, and also I would like to call print_warning_b() when print_a() of class A fires.

How can I modify the code to achieve this?

Thank you.

Gigino
  • 341
  • 3
  • 16
  • If I get it correctly, you are trying to implement an event system, you could take a look there: https://stackoverflow.com/questions/1092531/event-system-in-python – olinox14 May 13 '19 at 09:55
  • 1
    It looks like you don't totally get the difference between classes and instances... – bruno desthuilliers May 13 '19 at 10:10
  • It looks like you don't totally get the difference between someone who knows the differece between classes and istances and one who doesn't... – Gigino May 14 '19 at 07:05

1 Answers1

1

You need to connect A and B somehow. An event system is an alternative, but if it's just a learning exercise we can do something simpler. For example, by saving references to the other class in each other, like this:

class A:
    def __init__(self):
        self.a = "a"
    def set_other(self, other):
        self.other = other
    def print_a(self):
        print("A says:", self.a)
        self.other.print_warning()
    def print_warning(self):
        print("A says:", "Warning! B wrote something!")

class B:
    def __init__(self):
        self.b = "b"
    def set_other(self, other):
        self.other = other
    def print_b(self):
        print("B says:", self.b)
        self.other.print_warning()
    def print_warning(self):
        print("B says:", "Warning! A wrote something!")

if __name__=="__main__":
    class_a = A()
    class_b = B()
    class_a.set_other(class_b)
    class_b.set_other(class_a)
    class_a.print_a()
    class_b.print_b()

I had to set the references after creating the instances, because we have a circular dependency. Also notice the correct way to declare attributes inside a class: self.a = "a", inside the __init__() method. It works as expected:

A says: a
B says: Warning! A wrote something!
B says: b
A says: Warning! B wrote something!

Notice that the calls to the other reference are encapsulated inside methods, you're not supposed to expose calls like other.other.other to the outside world. In the end, there MUST be someplace where you have references to the other class (or references to both classes), it's unavoidable.

Óscar López
  • 232,561
  • 37
  • 312
  • 386
  • I din't post it, but this is quite similar to the solution I had in mind. The problem is that I don't really like to store one instance of a class inside another (and viceversa) because you could write: class_a.other.other.other.other.other ... .other.other and you can loose control on your actual reference... – Gigino May 13 '19 at 11:55
  • That's why calls to the "other" are encapsulated inside methods, you're not supposed to expose calls like other.other.other to the outside world. Bottomline, there MUST be someplace where you have references to the other class (or both classes), it's unavoidable. – Óscar López May 13 '19 at 12:23
  • Please, Oscar, add this your last comment in your answer (I found it more clarifying the the actual answer ^^), in this way I think I can accept it. Thank you again for your time! – Gigino May 14 '19 at 07:04
  • @Gigino I just did, thanks for your question and feedback :) – Óscar López May 14 '19 at 08:12