#python #logging #functional-programming
#python #ведение журнала #функциональное программирование
Вопрос:
В настоящее время я пытаюсь зарегистрировать функцию в python чистым способом.
Предположим, я хочу зарегистрировать функцию, которая имеет неясный list_of_numbers
аргумент as.
def function_to_log(list_of_numbers):
# manipulate the values in list_of_numbers ...
return some_result_computed_from_list_of_numbers
Когда значения в list_of_numbers
обрабатываются в вышеупомянутой функции, я хотел бы зарегистрировать это изменение, но не со значением в неясном list_of_numbers
, а со значением с тем же индексом во втором списке list_with_names_for_log
.
Что меня раздражает: теперь мне также приходится вводить list_with_names_for_log
, что раздувает список аргументов моей функции,
def function_to_log(list_of_numbers, list_with_names_for_log):
# do some stuff like, change value on 3rd index:
list_of_numbers[3] = 17.4
log.info('You have changed {} to 17.4'.format(list_with_names_for_log[3]))
# and so on ...
return some_result_computed_from_list_of_numbers
Я использую несколько из этих списков исключительно для входа в эту функцию.
Есть ли у кого-нибудь идея, как сделать это немного чище?
Комментарии:
1. Находятся ли списки, которые можно использовать для
list_with_names_for_log
аргумента, в той же области видимости, что и функция? Как вызывающее выражение решает, какой список использовать?2. Да, списки находятся в материнской функции, которая вызывает
function_to_log
их в качестве дополнительных аргументов. Какой список использовать жестко запрограммированfunction_to_log
: для некоторых манипуляций я просто использую одинlist_with_names
для ведения журнала, для некоторых манипуляций — комбинацию этих списков.3. Вероятно, в вашем вопросе недостаточно подробностей, чтобы обеспечить адекватное решение для ваших обстоятельств. Как указывает Carcigenicate, у вас есть пары списков, которые связаны их индексом, поэтому решение Carcigenicate может решить вашу проблему наличия нежелательного дополнительного параметра функции. Если существует связь между возвращаемыми значениями и аргументами, вы можете проверить возвращаемые значения и выполнить протоколирование в вызывающей функции. Возможно, используйте дескрипторы для значений данных и создайте дескриптор для регистрации при изменении. Или класс NamedData в Carcigenicate может быть разработан для регистрации при изменении.
Ответ №1:
При условии, что имеет смысл группировать данные, я бы сгруппировал пары имя / данные в структуру. В настоящее время у вас есть, по сути, «параллельные списки», которые обычно являются запахом, если вы не используете язык, на котором они являются вашим единственным вариантом.
Можно ввести простой класс данных:
from dataclasses import dataclass
@dataclass
class NamedData:
name: str
data: int
Затем:
def function_to_log(pairs):
pairs[3].data = 17.4
log.info('You have changed {} to 17.4'.format(pairs[3].name))
# and so on ...
return some_result_computed_from_list_of_numbers
В качестве образца данных:
pairs = [NamedData("Some Name", 1), NamedData("Some other name", 2)]
И если у вас есть два отдельных списка, его легко адаптировать:
pairs = [NamedData(name, data) for name, data in zip(names, data_list)]
Делайте это только в том случае, если вам обычно нужны оба бита в большинстве мест, где используется каждый список. Группировка поможет очистить код только в том случае, если имя и данные необходимы в большинстве мест, где используется либо одно, либо другое. В противном случае вы просто вводите накладные расходы и раздуваете их в другом месте, чтобы очистить несколько вызовов.