Craig
Craig

Reputation: 928

Python access base class data from all derived classes

I have a Python 3 program with a hierarchy of classes that are all ultimately derived from a single base class 'RootClass'. I want to be able to set a value from an object of any of the classes and see that value from any other object of those classes. My current solution, which works, uses a global variable that is accessed by object methods defined in 'RootClass'.

file1.py:

_myVal= None  # the global variable

class RootClass:
    def setVal(self, y):
        global _myVal
        _myVal= y
    def getVal(self):
        return _myVal

file2.py:

from file1 import RootClass

class A (RootClass):
    pass
class B (A):
    pass
class C (B):
    pass
class D (RootClass):
    pass

if __name__ == "__main__":
    objA = A()
    objB = B()
    objC = C()
    objD = D()
    objD.setVal(100)
    print(objA.getVal())
    print(objB.getVal())
    print(objC.getVal())
    print(objD.getVal())

Executing:

CMD> python file2.py
100
100
100
100

I realize globals are generally frowned upon, but nothing else I've considered seems quite as clean and simple.

Another option I considered is making a 'ValClass' object that has set/get methods. Then the set/get methods in RootClass would call that object's set/get methods. But that means I have to still create the ValClass object, and make sure it's accessible from all other objects, so I'm basically back to having a global.

What is a better/more Pythonic way of solving this?

Upvotes: 2

Views: 110

Answers (2)

Thierry Lathuille
Thierry Lathuille

Reputation: 24232

If you want it to look more pythonic, you can use properties:

class RootClass:  
    @property
    def val(self):
        return RootClass._myVal
    @val.setter
    def val(self, y):
        RootClass._myVal= y 

class A (RootClass):
    pass
class B (A):
    pass
class C (B):
    pass
class D (RootClass):
    pass

if __name__ == "__main__":
    objA = A()
    objB = B()
    objC = C()
    objD = D()
    objD.val = 100
    print(objA.val)
    print(objB.val)
    print(objC.val)
    print(objD.val)

Upvotes: 1

Taku
Taku

Reputation: 33714

Just need to set the scope to the class's scope for _myVal

class RootClass:
    def setVal(self, y):
        RootClass._myVal= y #Changed _myVal to be in RootClass's scope
    def getVal(self):
        return RootClass._myVal


class A (RootClass):
    pass
class B (A):
    pass
class C (B):
    pass
class D (RootClass):
    pass

if __name__ == "__main__":
    objA = A()
    objB = B()
    objC = C()
    objD = D()
    objD.setVal(100)
    print(objA.getVal())
    print(objB.getVal())
    print(objC.getVal())
    print(objD.getVal())

Upvotes: 1

Related Questions