#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
что-то с. Или, по крайней мере, с некоторыми аргументами. Хотя это может плохо читаться или быть неэффективным (я не знаю).
Мои идеи были:
- Соберите некоторые или все аргументы в список и «распакуйте» их в функции:
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
- Соберите их в словарь, например:
std_args = {"std_arg1": std_val1, "std_arg2": std_val2, ...} def f1(arg, std_args): # rewrite "std_arg1" -gt; std_args["std_arg1"]
- Поместите все аргументы в глобальную область, такие, которые известны каждой функции, что для меня звучит грязно, и я должен делать это в каждом модуле/файле.
- Используйте класс со списком или 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
. Каждый из аргументов имеет определенное имя, и у меня есть свобода добавлять аргументы или изменять аргументы в каждой функции без необходимости знать обо всех остальных аргументах.