多くの場合、複数のサブファンクションのパラメータを変更できるトップレベルの機能がある状況に遭遇します。私は、次の例としてこれを表現するだろう:私は私の内側の機能のためのすべてのデフォルトを再定義することを強制していますので、複数のサブファンクションをパラメータ化するためのベストプラクティス
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 = xとすべて)を含むようだ。 Iパーシャル(またはラムダ)を使用して、その周りを取得することができます:
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