8

実際、タイトルは私が聞きたい質問を正確に反映していません。私の目的は次のとおりです。matplotlib を使用していくつかのプロット関数を作成しています。さまざまなプロット目的のための一連の関数があります。線の場合は line_plot() 、バーの場合は bar_plot() など。例:

import matplotlib.pyplot as plt
def line_plot(axes=None,x=None,y=None):
    if axes==None:
        fig=plt.figure()
        axes=fig.add_subplot(111)
    else:
        pass
    axes.plot(x,y)

def bar_plot(axes=None,x=None,y=None):
    if axes==None:
        fig=plt.figure()
        axes=fig.add_subplot(111)
    else:
        pass
    axes.bar(left=x,height=y)

しかし問題は、定義された関数ごとに、コードのこの部分を繰り返さなければならないことです。

    if axes==None:
        fig=plt.figure()
        axes=fig.add_subplot(111)
    else:
        pass

コードの繰り返し部分を自動的に実行する、プロット関数の定義の前に適用できるデコレータを使用する方法はありますか? したがって、毎回繰り返す必要はありません。

考えられるオプションの 1 つは、次のような関数を定義することです。

def check_axes(axes):
    if axes==None:
        fig=plt.figure()
        axes=fig.add_subplot(111)
        return axes
    else:
        return axes

次に、例は次のようになります。

import matplotlib.pyplot as plt    
def line_plot(axes=None,x=None,y=None):
    axes=check_axes(axes)
    axes.plot(x,y)

def bar_plot(axes=None,x=None,y=None):
    axes=check_axes(axes)
    axes.bar(left=x,height=y)

しかし、より良い/クリーンな/よりpythonicな方法はありますか? デコレータを使用できると思いますが、わかりませんでした。誰かアイデアを教えてください。

ありがとう!!

4

1 に答える 1

6

デコレータでそれを行う方法は次のとおりです。

import matplotlib.pyplot as plt    

def check_axes(plot_fn):
    def _check_axes_wrapped_plot_fn(axes=None, x=None, y=None):
        if not axes:
            fig = plt.figure()
            axes = fig.add_subplot(111)
            return plot_fn(axes, x, y)
        else:
            return plot_fn(axes, x, y)
    return _check_axes_wrapped_plot_fn

@check_axes
def line_plot(axes, x=None, y=None):
    axes.plot(x, y)

@check_axes
def bar_plot(axes, x=None, y=None):
    axes.bar(left=x, height=y)

仕組み:@check_axes構文は、装飾された関数の名前を再定義します。たとえばline_plot、デコレーターによって作成された新しい関数、つまり_check_axes_wrapped_plot_fn. この「ラップされた」関数は、axesチェック ロジックを処理してから、元のプロット関数を呼び出します。

andのみの引数を取るプロット関数だけでなく、最初の引数としてcheck_axesan を取る任意のプロット関数をデコレートできるようにしたい場合は、Python の便利な構文を任意の引数リストに使用できます。axesxy*

def check_axes(plot_fn):
    def _check_axes_wrapped_plot_fn(axes=None, *args):
        if not axes:
            fig = plt.figure()
            axes = fig.add_subplot(111)
            return plot_fn(axes, *args)  # pass all args after axes
        else:
            return plot_fn(axes, *args)  # pass all args after axes
    return _check_axes_wrapped_plot_fn  

さて、これが「より良い/よりクリーンな/よりPythonic」であるかどうかは、おそらく議論の問題であり、より大きなコンテキストに依存します.

ところで、「より Pythonic である」という精神で、コードを再フォーマットして、PEP8スタイル ガイドに近づけました。パラメーター リストのコンマの後のスペース、=代入演算子の前後のスペース (ただし=、関数キーワード パラメーターに使用される場合を除く)、およびnot axes代わりに. と言うことに注意してくださいaxes == None

于 2012-08-02T12:17:40.163 に答える