3

I searched quite a bit on this, but can't seem to find anything specific to my problem.

Say I have three separate python files fileA.py, fileB.py, and fileMain.py

fileB.py inherits from fileA.py.

fileA.py

class Parent():
    def __init__(self):
        self.valueA = 5

fileB.py

from fileA import Parent

class Child(Parent):
    def __init__(self):
        Parent.__init__():
        self.valueB = 10

    def Calculate(self):
        self.result = self.valueB + self.valueA
        print(self.result)

And in fileMain.py I have some code that calls upon the Calculate method in the Child class AFTER valueA in the Parent class has been changed.

from fileA import Parent
from fileB import Child

class MainProgram():
    def __init__(self):
        self.parent = Parent()
        self.child = Child()

        self.parent.valueA = 8

        self.child.Calculate()

foobar=MainProgram()

My problem is, that the printed output is 15 and not 18. Why? How could I resolve this to get the expected result?

The reason I want for fileB.py to inherit from fileA.py is that I plan on having a fileC.py also inherit from fileA.py and have other calculations done there also using self.valueA. The valueA is supposed to be set by the user of the program. I simplified things here. Hope this makes sense?

Sorry if my use of terminology is wrong. Please correct me. :)

tiuq23
  • 113
  • 2
  • 11

1 Answers1

4

You seem to not be clear on how classes and instances (also referred to as objects) work.

Parent, Child and MainProgram are classes. You can think of them as blueprints. They do not change.

When you instantiate a class, you get an instance, e.g:

parent = Parent()
child = Child()

parent and child are instances. When you call parent.valueA = 8 you are changing a value on the instance called parent.

When you call child.Calculate() it has nothing to do with the parent instance. When you instatiated Child() the Parent() constructor was called and so child.valueA was set to equal 5. You would need to call child.valueA = 8 in order to change it.

For more information, consider reading through this: https://realpython.com/python3-object-oriented-programming/

(EDIT: By the way you refer to fileB inhereting from fileA and so forth. This an incorrect use of terminology. A file does not inherit from another file. You would say a module imports from another module. A class inherits from another class)

EDIT2:

If your goal is to share the state of Parent between all it's instances, you can use a Borg pattern for it. Essentially, every instance of the Borg shares its state with all other instances. So if you do parent1 = Parent() and parent2 = Parent(), and then do parent1.valueA = 8, then parent2.valueA will also equal 8.

It works like this:

class Parent(object): #This is a Borg class
    __shared_state = {}

    def __init__(self):
        self.__dict__ = self.__shared_state
        self.valueA = 5


class Child(Parent):
    def __init__(self):
        Parent.__init__(self)
        self.valueB = 10

    def Calculate(self):
        self.result = self.valueB + self.valueA
        print(self.result)


class MainProgram():
    def __init__(self):
        self.parent = Parent()
        self.child = Child()

        self.parent.valueA = 8

        self.child.Calculate()

foobar=MainProgram()
Karl
  • 5,573
  • 8
  • 50
  • 73
  • Thank you for the enlightenment! So if I have multiple classes inheriting valueA from the same parent class, I have to assign the new value to all the child classes individually? I was hoping there would be a more efficient way. – tiuq23 Dec 05 '18 at 21:46
  • What you are looking for is called a Borg pattern. I'll update my answer to show how it works. Personally I haven't really used it, so I can't give you the best explanation of why it works, but it will solve the problem you have. Here's an example: https://github.com/faif/python-patterns/blob/master/creational/borg.py. And here is a discussion you might find useful: https://stackoverflow.com/questions/1318406/why-is-the-borg-pattern-better-than-the-singleton-pattern-in-python – Karl Dec 05 '18 at 22:02
  • In Python, *everything* is an object, even classes. So there are classes and their instances. But an object may be a class, and an instance may be a class as well (all classes are instances of `type`, for example) – juanpa.arrivillaga Dec 05 '18 at 22:43
  • Yeah sure, technically speaking that is true. That doesn't help a beginner understand what is going on though. Outside the Python world `object` generally means the same as `instance` (even though there is some disagreement on that, mainly when people point to primitives: they aren't instances of anything, but the are objects; personally I prefer to refer to them as values rather than objects). Anyway, I do only mention `object` once, but refer to `instances` throughout – Karl Dec 05 '18 at 22:49