2012-08-02 3 views
5

実際、タイトルには質問したい質問が正確に反映されていません。私の目的は次のようなものです:matplotlibを使ってプロット関数を書いています。私は、異なるプロットの目的のための一連の機能を持っています。例えばバーなどの行のためのline_plot()、bar_plot()のように:関数の引数のデフォルト値を自動的に置き換えるためにpythonデコレータを使用しますか?

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 

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

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) 

しかし、より良い/クリーン/より多くの神託の方法はありますか?私はデコレータを使うことができますが、それを理解していないと思います。誰かが何か考えを与えることができますか?

ありがとうございます!ここで

+2

あなたの最後の解決策はかなり良いと思います。関数は、コードを構造化する効率的で実績のある方法です。私はデコレータが物事を不必要に複雑にすると思う。 –

+0

おそらく、あなたの答えのために、 – zenpoy

答えて

7

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

どのように動作
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 - チェックロジックを処理し、元のプロット関数を呼び出します。

あなたはcheck_axesものみxyの引数を取り、あなたが任意の引数リストのためのPythonの便利な*構文を使用することができるだけでなく、それらの、その最初の引数としてaxesを取る任意の関数plotを飾ることができるようにしたい場合は、次の

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 

ここでは、いずれかが「より良い/クリーナー/もっとPython」であるかどうかは、おそらく議論の対象となり、より大きな文脈に依存します。

ちなみに、「もっとPythonic」であるという精神で、PEP8スタイルガイドに近づくようにコードを再フォーマットしました。代入演算子の=(ただし、=が関数キーワードパラメータに使用されている場合)の周囲の空白で、axes == Noneの代わりにnot axesと指定すると、パラメータリストのカンマの後の空白に注意してください。

+1

こんにちはGhopper21に感謝のあなたのテストでAxesクラスを作成することができます。これは私が見たいものです。はい、それはより多くのpythonicの大きい写真を考慮する必要がありますかどうか。また、コードの再フォーマットに感謝し、再フォーマットされた方がより良く見えます:) – wiswit

関連する問題