0

I'm working with data science and I have a pretty big script consisting of a lot of helper functions to run analysis on pandas dataframes and then one main function that utilizes my functions to get some results.

The issue is that most or the function inputs are just names of the columns in the dataframe (because they are taken as input from users) and this leads to a lot of functions have partially the same input.

What I wonder is if it possible to have a dict containing all my parameters and simply pass the dict to every function without modifying the dict? That is, each function would have to ignore the keywords in the dict that are not an input to that particular function.

To give an example say I have this function.

    def func1(a, b, c):
        return a + b * c

And I have this dict containing the inputs to all my functions.

    input_dict = {'a': 1,
                 'b': 2,
                 'c': 3,
                 'd': 4}

If I call this function with this dict as input like this:

    value = func1(**input_dict)

I will get an error because of the unexpected argument d.

Any workaround here that doesnt involve altering the dict? My code works but I would love to get away from having so many repeated input arguments everywhere.

Thanks in advance :)

Fredrik Nilsson
  • 549
  • 4
  • 13
  • 1
    Change the function def to `def func1(a, b, c, **kwargs)` so it takes [any number of keyword args](https://stackoverflow.com/questions/1769403/what-is-the-purpose-and-use-of-kwargs). Or even simpler `def func1(**kwargs)` – pault Mar 11 '20 at 17:19
  • 2
    If you feel the need to package your arguments into a `dict` for calling your helper functions, that's a good sign that you might want to define a class with the helper functions as methods. An instance of your class then acts as the `input_dict`. You go from `func1(**input_dict)` to `d = Foo(**input_dict); d.func1()`. The definition of `func1` then uses those instance attributes it needs. – chepner Mar 11 '20 at 17:22
  • 1
    IMO this is still a duplicate of [How does one ignore unexpected keyword arguments passed to a function?](https://stackoverflow.com/questions/26515595/how-does-one-ignore-unexpected-keyword-arguments-passed-to-a-function). Posting here because the timeline doesn't store the duplicate link. – pault Mar 11 '20 at 17:34
  • Does this answer your question? [How does one ignore unexpected keyword arguments passed to a function?](https://stackoverflow.com/questions/26515595/how-does-one-ignore-unexpected-keyword-arguments-passed-to-a-function) – AMC Mar 11 '20 at 18:40

1 Answers1

0

What I wonder is if it possible to have a dict containing all my parameters and simply pass the dict to every function without modifying the dict?

That's a pretty good summary of the use case for a class.

from operator import attrgetter


class Foo:
    def __init__(self, a, b, c, d):
        self.a = a
        self.b = b
        self.c = c
        self.d = d

    def func1(self):
        a, b, c = attrgetter('a', 'b', 'c')(self)
        return a + b * c

f = Foo(1, 2, 3, 4)

value = f.func1()

The instance of your class replaces input_dict. Each helper function becomes an instance method, with its definition using only those instance attributes it needs.

My use of attrgetter is just a suggestion for helping migrate your existing functions into methods, as it doesn't require scattering a bunch of references to self throughout. You can define func1 simply as

def func1(self):
    return self.a + self.b * self.c
chepner
  • 497,756
  • 71
  • 530
  • 681
  • Yea my initial idea was actually to migrate it over to a class based structure instead and my question here was basically my attempt at working around the issue. When I initially made this script I wasnt aware how much it would be scaled up and that it would contain so many functions. I guess it might just be worth spending some time migrating it over, thanks for the input :) – Fredrik Nilsson Mar 11 '20 at 17:35