Elegant way to deal with multiple args in __init__ function

Question:

I have the follow init function who receives a lot of args to run the class (the args are default values if the user don’t input anything or can be a value inputed by the user). What’s the most elegant way to reduce the number of variables (not show a lot of args in the init) without lose readability? Use the *args function (like def__init__(self, *args))?

    class World(object):
    
        def __init__(self, grid_size=(GRID_WIDTH, GRID_HEIGHT),
                     cell_size=(CELL_WIDTH, CELL_HEIGHT),
                     obstacles_position= OBSTACLES,
                     recharge_position= RECHARGE_ZONE,
                     treadmill_position= TREADMILL_ZONE,
                     workers_positions= WORKERS_POS,
                     delivery_positions= DELIVERY_ZONE):
         # some code bellow
    def main():
       # init some libraries
       world = worldGrid()
       # Do a while loop with the input variables from the world class

    if __name__ = '__main__':
       main()
Asked By: Ircbarros

||

Answers:

In my opinion, you should probably stick with all of the function parameters in the function header (as you currently have it). This makes your code more readable, allows Python to tell you which arguments you may have omitted, plays nicely with Python’s built-in help() method, allows third-party IDE code hinting, etc., etc…


If you really want to shorten the function header, you could use *args and **kwargs which will take any variadic arguments, e.g.:

def func(self, *args, **kwargs):
    print("args:", args)
    print("kwargs:", kwargs)

Usage would look like this:

>>> func(1, 2, 3, one="ONE", two="TWO")
args: (2, 3)
kwargs: {'one': 'ONE', 'two': 'TWO'}

Therefore, you could theoretically refactor your class to look something like below. This code doesn’t handle default values or any error checking at all — it just sets any keyword-arguments as attributes on the class itself:

class World(object):
    def __init__(self, **kwargs):
        for key, value in kwargs.items():
            setattr(self, key, value)

And usage:

>>> w = World(one=1, two=2, three=3)
>>> w.one
1
>>> w.two
2
>>> w.three
3
Answered By: Benjamin
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.