2

I have the following code where I need to pass all the arguments from one function to another. I want to know a way avoid the long list of arguments. I only "know" there is "*" and "**" in python, but I have never used them before.

# definition
    def TestCase(test_name, op_type, input_shapes, op_args, run_mode):
        # all those arguments are unchanged before passing to 
        # "add_tester"
         ...

        # another function, the long list of arguments doesn't look 
        # good to me  
        add_tester("c2", test_name, input_shapes, op_args, run_mode, benchmark_func)

# Call TestCase
TestCase(
test_name='mm',
op_type='MM',
input_shapes=input_shapes,
op_args={'trans_a': trans_a, 'trans_b': trans_b},
run_mode=run_mode)
Zack
  • 1,205
  • 2
  • 14
  • 38
  • you can pass a dict. For example: `TestCase(**Your_DICT)` and like this you'll unpack tyour dict and use it's kyes & values inside your class as arguments. – Chiheb Nexus Mar 27 '19 at 22:08
  • In general, you create a class/object that wraps all related parameters. https://refactoring.guru/smells/long-parameter-list – OneCricketeer Mar 27 '19 at 22:19

3 Answers3

2

Write a class, put in the parameters at __init__, and use self.

class TestCase:
    def __init__(self, test_name, op_type, run_mode, benchmark_func):
        self._test_name = test_name
        self._op_type = op_type
        self._run_mode = run_mode
        self._benchmark_func = benchmark_func
        # bunch of initiation code follows

    # another function, the long list of arguments doesn't look 
    # good to me  
    def run_test(self, op_args, idk_what_this_is="c2"):
        # access self._XX for the fields

A few notes:

  1. Be careful with naming conventions. Use lowercase with underscore for functions/methods.
  2. If you are doing conventional testing, consider existing frameworks like nose. There are lots of code pattern that you don't need to rewrite by doing so.
Pik-Mai Hui
  • 311
  • 1
  • 7
0

If you are interested about how to use * and ** notations look at the example:

def f(a, *args, **kwargs):
     print("a: %s, args: %s, kwargs: %s" % (a,args, kwargs))

f(1, 2, 3, 4, b=5, c=6, d=7)
# output: A: 1, args: (2, 3, 4), kwargs: {'b': 5, 'c': 6, 'd': 7}

What does ** (double star/asterisk) and * (star/asterisk) do for parameters? contains a good explanation on this things.

As for your code if you don't want to pass all your arguments one by one, you can use **kwargs for all your variables:

# definition
def TestCase(**kwargs):
    # all those arguments are unchanged before passing to 
    # "add_tester"
     ...

    # another function, the long list of arguments doesn't look 
    # good to me  
    add_tester("c2", kwargs)

# Call TestCase
TestCase(test_name='mm', op_type='MM', input_shapes=input_shapes, op_args={'trans_a': trans_a, 'trans_b': trans_b}, run_mode=run_mode)

But you will need to refer to your arguments as kwargs['test_name'], kwargs['op_type'], ... and your arguments become optional, whoever calls your method will not see what actual arguments are expected.

andnik
  • 2,405
  • 2
  • 22
  • 33
-3

You can use global variables. Global variables are the one that are defined and declared outside a function and we need to use them inside a function. GeeksforGeeks has some examples: https://www.geeksforgeeks.org/global-local-variables-python/ There's also the config file. The canonical way to share information across modules within a single program is to create a special module (often called config or cfg). Just import the config module in all modules of your application; the module then becomes available as a global name. See python faq's: https://docs.python.org/3/faq/programming.html#how-do-i-share-global-variables-across-modules

Mr Ed
  • 83
  • 2
  • 12