Я часто сталкиваюсь с ситуацией, когда у меня есть функция верхнего уровня, из которой я хочу иметь возможность изменять любой из параметров нескольких подфункций. Я выражаю это в следующем примере:Лучшая практика для параметризации нескольких подфункций
def plot_data_processing(data_param_1=3, data_param_N=4,
processing_param_1='a', processing_param_2='b', plotting_param_1='c',
plotting_param_2=1324):
data = get_data(data_param_1=data_param_1, data_param_1=data_param_N),
processed_data = process_data(data, processing_param_1=processing_param_1, processing_param_2=processing_param_2)
plot_data(processed_data, plotting_param_1=plotting_param_1, plotting_param_2=plotting_param_2)
Теперь это своего рода некрасиво, потому что я вынужден пересмотреть все значения по умолчанию для своих внутренних функций, и мои параметры один большой беспорядок. Я предполагаю, что я мог бы сделать следующее:
def plot_data_processing(data_kwargs, processing_kwargs, plotting_kwargs):
data = get_data(**data_kwargs),
processed_data = process_data(data, **processing_kwargs)
plot_data(processed_data, **plotting_kwargs)
plot_data_processing(dict(data_param_1=3, data_param_N=4), dict(processing_param_1='a', processing_param_2='b'), dict(plotting_param_1='c',plotting_param_2=1324))
Тем не менее, это не является большим, потому что я делаю эту странную практику передачи аргументов через Словарь, где они ждут только для функции будет называться быть подтверждено , Кажется, это рецепт ошибок и нечитаемый код. Кроме того, у меня нет свободы менять функции, называемые внутри, для разных функций с аналогичным интерфейсом. Так что я мог бы также пойти:
def plot_data_processing(data_getter, data_processor, plotter):
data = data_getter(),
processed_data = data_processor(data)
plotter(processed_data)
class DataGetter(object):
def __init__(self, data_param_1=3, data_param_N=4):
self.data_param_1 = data_param_1
self.data_param_N = data_param_N
def __call__(self):
# ....
return data
# ... Also define classes DataProcessor and Plotter
plot_data_processing(DataGetter(data_param_1=3, data_param_N=4), DataProcessor(processing_param_1='a', processing_param_2='b'), Plotter(plotting_param_1='c',plotting_param_2=1324))
Однако это также, кажется, включать ненужную структуру и код пушистой (self.x = х, и все, что). Я могу обойти, что с помощью парциальных (или лямбды):
def plot_data_processing(data_getter, data_processor, plotter):
data = data_getter(),
processed_data = data_processor(data)
plotter(processed_data)
# Called like:
plot_data_processing(
data_getter = partial(get_data, data_param_1=3, data_param_N=4),
data_processor = partial(process_data, processing_param_1='a', processing_param_2=3),
plotter = partial(plot, plotting_param_1='c', plotting_param_2=1342),
)
Но это также, кажется, неудовлетворительного - потому что нет четкого «типа» аргументов для вызова функции с - только частичной функцией, которая должна работать при вызываемый - затрудняет работу другого программиста, который хочет использовать эту функцию.
Итак, ни один из этих методов не дает мне чувствовать себя выполненным или счастливым. Наверное, мне нравится частичный, но я хотел бы каким-то образом объявить, что частичная функция подчиняется некоторому интерфейсу.
Кто-нибудь знает лучший способ?
Что значит «заявить, что частичная функция подчиняется некоторому интерфейсу» *? – jonrsharpe
Например, моя функция «data_getter» не должна принимать никаких аргументов и возвращать какой-либо объект данных. Мой «data_processor» должен взять какой-то объект данных и вернуть обработанный объект данных. Я хочу, чтобы функции, которые были переданы, подчинялись этим интерфейсам и могли утверждать, что они делают это до их вызова. Вы можете сделать это с помощью классов (assert isinstance (data_getter, DataGetter)), но я ищу эквивалент, когда объект data_getter является частичной функцией, а интерфейс DataGetter указывает на ввод/вывод функции, а не методы для класс. – Peter
На самом деле это не то, что вы делаете на Python.Обычно мы придерживаемся утиного ввода: если вы передаете что-то, что имеет соответствующий интерфейс, все работает, если не вы получаете 'TypeError' (или другое исключение). Нет никакой разницы между функциями и методами. – jonrsharpe