我经常遇到一种情况,我有一个顶级函数,我希望能够修改多个子函数的任何参数。我将以下面的例子表示:
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))
但是,这并不是很好,因为我正在做这种通过dict传递参数的奇怪做法,他们只等待调用函数进行验证。看起来像是错误和不可读代码的配方。此外,我没有自由交换内部调用的函数用于具有类似接口的不同函数。所以我也可以去:
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 = x和所有这些)。我可以通过使用partials(或lambdas)来解决这个问题:
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),
)
但这似乎也不令人满意 - 因为没有明确的“类型”参数来调用函数 - 只是一个部分函数应该在调用时起作用 - 使另一个想要使用该函数的程序员更难。 / p>
所以,这些方法都没有让我感到满足或快乐。我想我喜欢偏爱,但是我想要某种方式来声明部分函数服从某个接口。
有人知道更好的方法吗?
答案 0 :(得分:1)
Python 3.5有一个新的(可选的)类型提示系统可能会做你想要的。 Python解释器在运行时不会检查它,但允许您创建有关参数类型和返回函数值的语句。可以在代码上运行单独的静态分析器程序,如mypy
,以查找键入错误。
对于您的plot_data_processing
功能,我认为您想宣布以下内容:
from typing import Callable, TypeVar
DataType = TypeVar("DataType")
ProcessedDataType = TypeVar("ProcessedDataType") # could be the same as DataType
def plot_data_processing(data_getter: Callable[[], DataType],
data_processor: Callable[[DataType], ProcessedDataType],
plotter: Callable[[ProcessedDataType], None]) -> None:
...
如果DataType
函数使用与原始数据相同的类型返回相同的处理数据,则可能只能使用一个data_processer
而不是两个Sequence[float]
。您还可以更具体地指定这些类型(例如,使用TypeVar
或其他类型,而不是使用link
),如果您不需要通用方法。
有关详细信息,请参阅PEP 484和文档the typing
module。