0

I am looking to create a run configuration class called Global that will store important variables. This class will be passed to many classes and their children. For example:

class Global:
    def __init__(self):
        self._var = 1

    @property
    def var(self):
        return self._var

class parent:
    def __init__(self, GLOBAL):
        self.GLOBAL = GLOBAL
        print(self.GLOBAL.var) # this works

class child(parent):
    def __init__(self):
        print(self.GLOBAL.var) # this doesn't work (because referencing the parent's instance variable)

How can I make the Global class accessible to all children of the parent class (without passing it to each child's constructor)? I also tried creating a class variable in the parent class and assigned it's value when the class is initialized. However, that didn't work.

Also, if there is a better way to store mutable run configurations and pass them to many classes and their children I'd be happy to change my strategy.

Thanks a ton in advance!

Michael Berk
  • 705
  • 7
  • 23
  • 1
    Your `__init__` Nevers sets the attribute in your subclass and it overrides the superclass one that does... This really has nothing to do with your global class at all, this would work the same with any attribute – juanpa.arrivillaga May 12 '20 at 22:40
  • Hi Juanpa - I thought you don't need to initialize ```GLOBAL``` in the child class because it will be inherited from the parent. Is this wrong? – Michael Berk May 12 '20 at 22:47
  • 1
    Why use class inheritance at all? Just do `GLOBAL = Global()` at the module level and all of your other classes can reference it. – tdelaney May 12 '20 at 23:06
  • Hi @tdelaney - thanks for the answer but the Global class needs to be mutable across modules and those changes need to be accessible by all modules. I think your solution would create a new instance for each module. – Michael Berk May 12 '20 at 23:15
  • 2
    No, it would only be in the module where `GLOBAL = Global()` is set. If that's the same module where `class parent` is defined, then some module that wants to inherit from parent would also use `import parentmodule; parentmodule.GLOBAL`. In fact, you could put `GLOBAL = Global()` at the parent class level. – tdelaney May 12 '20 at 23:20
  • 1
    There is the question of when `Global()` should be instantiated - if its `__init__` is reading configuration, that may be a bad thing. But if its used before the real configuration happens, that's a bad thing tool. That's the advantage of it just being at the module level. Your code can initialize it after everything's been imported but before the classes have been instantiate it. – tdelaney May 12 '20 at 23:22
  • 1
    `self._var = 1` suggests that different instances of these classes can get different configurations. Is `Global` to be considered a singleton? – tdelaney May 12 '20 at 23:26
  • @tdelaney thanks for all this. First, yes ```Global``` will be treated like a singleton (for now). Second, declaring at a module level then importing ```Global``` from a different module works beautifully. That is what I will use going forward. Thank you again! If you have other tips/resources I'd love to know. – Michael Berk May 12 '20 at 23:36

2 Answers2

2
  1. Your child class should call parent __init__ method like this:

    super().__init__(...)

Otherwise you won't set GLOBAL field at all. I guess you can read more here.

  1. You want to create a global object, don't you? I mean, not a class, but the object of that class, because you're accessing variable var in your constructor. Anyway, you can just create a variable in your module scope and use it.

    Global: ...

    OtherClass: def run(self): print(_global_settings)

    _global_settings = Global() # or something similar

  2. You'd better follow PEP8 style if possible, then your code will be easier to read and understand. In particular, capitalize your class names and use lowercases for class fields.

stardust
  • 593
  • 7
  • 9
  • Hi @stardust thanks for the response. The global object needs to be referenced across modules, but that would have worked well. And noted on the style. – Michael Berk May 12 '20 at 23:18
1

If your child class does not override the constructor __init__, then parent.__init__ will be used when constructing child objects, and you will get the functionality you want. If you need to write specialized constructors to your derived classes, however, you will need to pass the Global object to an explicit call of the parent.__init__ constructor within child.__init__.

Python does not have automatic constructor chaining.

Amitai Irron
  • 1,973
  • 1
  • 12
  • 14