Упрощение подписи вызова для многократно используемых аргументов

#python #signature

Вопрос:

У меня есть куча функций с похожими входными данными. Это означает, что существует список стандартных аргументов, которые присутствуют неоднократно, и некоторые из них могут отличаться:

 def f1(arg, std_arg1, std_arg2, ...):  # do something  def f2(another_arg, std_arg1, std_arg2, ...):  # do something else  

Теперь я хотел бы упростить подпись вызова, имея список или словарь, содержащий все параметры. Таким образом, проще вызывать все различные функции, а также писать новые функции. Эта проблема усугубляется тем фактом, что функции могут вызывать другие функции из других модулей/файлов с подписью, снова содержащей многие из этих аргументов, таких как:

 def super_f(arg1, arg2, std_arg1, std_arg2, ...):  # depending on some args call eventually  f3(arg2, std_arg1, std_arg2, ...)  

,где f3 снова вызывает что-то с, например arg2 , и std_arg2 Я хочу привести в порядок код, и теперь вопрос в том, какой здесь самый чистый способ. В идеале я хотел бы иметь что-то вроде:

 def super_f(all_the_args):  # depending on some args call eventually  f3(all_the_args)  

откуда f3 снова звонит all_the_args что-то с. Или, по крайней мере, с некоторыми аргументами. Хотя это может плохо читаться или быть неэффективным (я не знаю).

Мои идеи были:

  1. Соберите некоторые или все аргументы в список и «распакуйте» их в функции:
 std_args = [std_arg1, std_arg2, std_arg3, ...] # or potentially all the args def f(arg, std_args):  std_arg1, std_arg2, ... = std_args  # do something  
  1. Соберите их в словарь, например:
 std_args = {"std_arg1": std_val1, "std_arg2": std_val2, ...} def f1(arg, std_args):  # rewrite "std_arg1" -gt; std_args["std_arg1"]  
  1. Поместите все аргументы в глобальную область, такие, которые известны каждой функции, что для меня звучит грязно, и я должен делать это в каждом модуле/файле.
  2. Используйте класс со списком или dict в качестве входных данных для конструктора, где хранятся все параметры, а затем известны в этой области.
 def class func(object):  def __init__(self, std_args):  self.std_arg1 = std_args[0]  self.std_arg2 = std_args[1]  ...    def f1(self, arg):  # do something with arg, std_arg1, std_arg2, ...   

Это может быть самым чистым решением, но требует некоторой переписки (хорошо, потенциально просто найти-gt;заменить), и в моем коде много gt;запутанных self. .

Для варианта 1, 2, 3 я думаю, что я должен сделать это на каждом «уровне» вызывающей структуры. Возможно, с помощью варианта 4 это будет проще сделать во всех «уровнях» /файлах.

Есть ли лучшее решение этой проблемы? Или есть какие-либо предложения, как написать этот код в лучшей структуре?

Комментарии:

1. Знакомы ли вы с *args и **kwargs dict?

2. Немного. Я думаю, что таким образом я могу решить «один из способов», определив def f(*args): ... , но мне все равно нужно записать это при вызове функции (насколько я знаю) с помощью : f(arg1, arg2, arg3, ...) вместо f(*args) . И тогда все равно имя самой переменной неизвестно функции, так что я не могу использовать ее, например, с «x = arg1 * 5». Это может быть решено в некоторой степени с помощью диктанта в **kwargs

3. Мне приходилось писать много подобного кода, и я склонен им пользоваться **kwargs . Каждый из аргументов имеет определенное имя, и у меня есть свобода добавлять аргументы или изменять аргументы в каждой функции без необходимости знать обо всех остальных аргументах.