简体   繁体   中英

How to avoid repeated arguments in function call in Python 3

How can you avoid repeating the same arguments over and over in Python in a similar method call?

For example in this snippet:

for col in self.numerical_columns:
    self.comp_train_df = self.comp_train_df.merge(self.get_aggregates(self.train_df, col), left_index=True, right_index=True)
    self.comp_test_df = self.comp_test_df.merge(self.get_aggregates(self.test_df, col), left_index=True, right_index=True)

these parameters are repeated:

left_index=True, right_index=True

Ideally you would define the repeated parameters in a variable and re-use them. I have tried this code, but as a Python newbie I am not sure if this is the right approach:

merge_args = {'left_index':True, 'right_index':True}
for col in self.numerical_columns:
    self.comp_train_df = self.comp_train_df.merge(self.get_aggregates(self.train_df, col), **merge_args)
    self.comp_test_df = self.comp_test_df.merge(self.get_aggregates(self.test_df, col), **merge_args)

This is an interesting question, and I remember that I have done this with decorators once. It might be overkill, but maybe its worth a consideration.

Consider a function with multiple keyword arguments, like this function:

def yell(sound='woof', volume='loud', pitch='high')
    return f'{sound} -> {volume} -> {pitch}'

Let's say you want to use this function multiple times in a row, but the volume is only medium. In this case, you have to call the function with the volume argument everytime. Instead of doing this, you could decorate the function and change its default params to your liking.

def change_default(**new_kwargs):
    def wrapper(func):
        def new_fn(*args, **kwargs):
            for key, val in kwargs.items():
                if key in new_kwargs:
                    new_kwargs[key] = kwargs.pop(key)
            return func(*args, **kwargs, **new_kwargs)
        return new_fn
    return wrapper

Essentially, you create a parametrizable decorator, that takes your function and changes its default args. All other kwargs are not affected, but can be changed manually if needed.

Coming back to the usecase, you would decorate it like this:

@change_default(volume='medium')
def yell(sound='woof', volume='loud', pitch='high')
    return f'{sound} -> {volume} -> {pitch}'

Upon calling the yell function, it returns:

woof -> medium -> high

I found this to be more comfortable than passing a dictionary in some cases.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM