Search code examples
pythonfunctionclassconfigurationinstance

Creating instances of a function via a configuration file


We have a configuration file that is read and stored as a dictionary, e.g.

config = {'type': A, 'input': {'color': 'red', 'border': 'thick', 'shape': 'square'}}

Now we want to use this config object to create an instance of a class, say, Drawing_Class with the condition that if the type is 'A', the colour is always blue, and if the type is 'B' the shape is always a circle.

I have written a function to achieve this which seems very unpythonic, and was wondering if there is a better way to achieve my goal? Of course, in the example I've given one could just input the desired colour and shape in the configuration file, but the actual problem is more complex and that can't be achieved.

Here is my function.

def drawing_dictionary(type):
    if type == 'A':
        value = config['inputs'].pop('color')
        output = drawing_function(**config['inputs'], colour='blue')
        config['input']['color'] = value

    if type == 'B':
        value = config['inputs'].pop('shape')
        output = drawing_function(**config['inputs'], shape='circle')
        config['input']['shape'] = value

    return output

It achieves what I need it to achieve, i.e. creating custom instances based on this configuration file, but in a way that seems very inelegant. Help would be much appreciated.


Solution

  • I like to use dicts to take the place of potentially-large if-elif blocks, so the first thing I would do is to create a lookup for the type names, containing the field name and default value for each type.

    types = {
        "A": ("color", "blue"),
        "B": ("shape", "circle"),
    }
    

    I would also recommend copying the contents of the config table, rather than modifying it. This will keep you from accidentally modifying it, and also makes the function re-entrant. Here's my version:

    def drawing_dictionary(typename):
        key, default = types[typename]
        kwargs = config["inputs"].copy()
        kwargs[key] = default
        return drawing_function(**kwargs)
    

    With this implementation, supporting a new type is as simple as adding a row in types, rather than defining a new if block.