Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python initialize class with variables in init file and default constants file

Tags:

python

oop

I have a class with a long list of variables (at least a dozen). In the module I first import a constants file which contains some helper methods and all of the default constants.

from myConstants import *

class SomeClass(ParentClass):
    def __init__(var1=VAR1, ..., varN=VARN):
        super(SomeClass, self).init(var1, ...)
        self.varM = varM

PROBLEM: I would like to be able to specify a file when I initialize the class where the file contains a subset of the constants in myConstants.py. The variables not in the init file would be loaded from the defaults. Something like:

sc = SomeClass(initFile='/path/to/file')

My thought was to have something like

from myConstants import *
from ConfigParser import SafeConfigParser

class SomeClass(ParentClass):
    def __init__(var1=VAR1, ..., varN=VARN, initFile=''):
        if initFile: 
            parser = SafeConfigParser().read(initFile)
            var1 = parser('constants', 'var1') if parser('constants', 'var1') else VAR1
            var2 = parser('constants', 'var2') if parser('constants', 'var2') else VAR2
            ....
            varN = parser('constants', 'varN') if parser('constants', 'varN') else VARN
        else:
            var1 = VAR1
            ...
            varN = VARN

        super(SomeClass, self).init(var1, ...)
        self.varM = varM

QUESTION: Is this the best way to do this? If not, what is? Seems a little long winded. I'm also not married to ConfigParser.

like image 594
Sal Avatar asked Jan 29 '26 10:01

Sal


2 Answers

I would use two separate constructors, one that takes a file and another that takes explicit arguments.

class SomeClass(ParentClass):
    @classmethod
    def from_file(cls, init_file):
        parser = SafeConfigParser()
        parser.read(init_file)
        var1 = parser.get('constants', 'var1') if parser.has_option('constants', 'var1') else VAR1
        # likewise var2, ..., varN
        # This results in a call to cls.__init__
        return cls(var1, var2, ..., varN)

    def __init__(var1=VAR1, ..., varN=VARN, initFile=''):            
        var1 = VAR1
        ...
        varN = VARN

        super(SomeClass, self).init(var1, ...)
        self.varM = varM

x = SomeClass(1, 2, 3)
y = SomeClass.from_file(config_file)
like image 116
chepner Avatar answered Jan 31 '26 01:01

chepner


Man, this ConfigParser clearly shows its age - it definettely should have a mapping interface - I had to poke a little around to get a way to get its values - but this is a more suitable code for you:

class SomeClass(ParentClass):
    options = {"var1": VAR1, "var2": VAR2, ...} 
    def __init__( initFile='', **kwargs):
        options = self.__class__.options.copy()
        if initFile: 
            parser = SafeConfigParser().read(initFile)
            for option_name in parser.options("constants"):
                if options_name in options:
                    options[option_name] = parser.get("constants", option_name)
        else:
            for key, value in kwargs:
                if key in options:
                    options[key] = value

        super(SomeClass, self).init(**options)
        self.varM = varM
like image 30
jsbueno Avatar answered Jan 31 '26 01:01

jsbueno