2017-01-17 7 views
18

私が開発したすべてのモジュールをメインプログラムに入れたときに問題が発生しました。私が作成したスイッチ辞書は以下の通りです:スイッチ辞書内の関数の実行

def Tank_Shape_Calcs(Tank_Shape, level, area, dish, radius, length, Strapping_Table, Tank_Number): 

    switcher = { 
     0: vertical.Vertical_Tank(level, area), 
     1: horiz.Horiz_Cylinder_Dished_Ends(dish, radius, level, length), 
     2: strapping.Calc_Strapped_Volume(Strapping_Table, level), 
     3: poly.Fifth_Poly_Calcs(Tank_Number) 
    } 
    return switcher.get(Tank_Shape, "ERROR: Tank type not valid") 

タンクの形状は、各タンクのループでメインファイルに設定されています。最初のタンクにはTank_Shape = 2がありますので、Calc_Strapped_Volume()関数を実行すると思います。

私はそれをテストしようとしましたが、スイッチャー機能はTank_Shapeを確実に2と読んでいます。また、関数を文字列に変更すると、正しい文字列が出力されます。

問題は、正しい関数が呼び出されるまで関数が順番に実行されているように見えることです。これは、私が使用しているデータが正しい関数でのみ動作するため、エラーが発生します。

正しい機能のみを実行する方法はありますか?

+5

あなたのコードを構造化しまし方法(手動または所望の動作に応じて、必要とされないことがあり、いくつかの異なる引数を、複数の行動を扱う組み合わせるためのラムダの辞書を使用して、&cが。)あなたは、Pythonに新しいしていることを示唆しています。あなたのコードのより完全なコピーをcodereview.stackexchange.comに投稿することをお勧めします。そこにユーザーのいくつかのあなたに、より効果的にあなたのコードを記述する方法についていくつかのヒントを与えることができるかもしれません: ') – gntskn

答えて

34

すべての機能は、キーにアクセスしたときではなく、辞書を作成するときに実行されます。

switcher = { 
    0: lambda : vertical.Vertical_Tank(level, area), 
    1: lambda : horiz.Horiz_Cylinder_Dished_Ends(dish, radius, level, length), 
    2: lambda : strapping.Calc_Strapped_Volume(Strapping_Table, level), 
    3: lambda : poly.Fifth_Poly_Calcs(Tank_Number) 
} 

、あなたが戻ったときに呼び出す、ラムダなどのエラーメッセージが表示されて:あなたは必要なときに関数がのみ呼び出されることを確認する(パラメータなしで、彼らはすでに知られている)lambdaを使用する必要が

return switcher.get(Tank_Shape, lambda : "ERROR: Tank type not valid")() 
+8

または_functools.partial_代わりにラムダ – volcano

+0

のはfunctools.partial' '知りませんでした。 Dulyは指摘する。すべての引数が渡されているので、しかし、その場合には、 'lambda'が最良の選択であると思われる(私は将来の答え:)でそれを再利用したいと考えています)だけでなく、いくつかの...常に幸せ –

+2

が:-)サービスであることが、 _partial_はコールバックに優れています。私自身は_lambda_で頻繁に罪を犯しますが、 - IMHO、この場合は_partial_は少しきれいに見えます。味の物質。 – volcano

7

あなたのコードで何をしているのかは、整数キー(0-3)と関数結果を値として持つ辞書を作成することです。したがって、まずすべての関数を呼び出してから、これらの関数の戻り値にアクセスします。

def Tank_Shape_Calcs(Tank_Shape, level, area, dish, radius, length, Strapping_Table, Tank_Number): 
    switcher = { 
     0: (vertical.Vertical_Tank, (level, area)), 
     1: (horiz.Horiz_Cylinder_Dished_Ends, (dish, radius, level, length)), 
     2: (strapping.Calc_Strapped_Volume, (Strapping_Table, level)), 
     3: (poly.Fifth_Poly_Calcs, (Tank_Number,)) 
    } 
    func, args = switcher.get(Tank_Shape, (None, None)) 
    if func is not None: 
     return func(*args) 

ここでは、まず引数を指定して呼び出す関数を呼び出して呼び出します。

+0

だ:私は、迅速な学習者です良い考え。しかし、エラーメッセージをエミュレートしなかったので、 'Tank_Shape'が> 3の場合、クリアエラー文字列を返す代わりにクラッシュします。 –

+0

はい、あなたは正しいです、私は小切手を入れました – BloodyD

+1

私にこれはこれまで提案された最もエレガントな解決策のように感じます。 – SethMMorton

17

前述のように、関数は辞書の構築中に呼び出されます。それに加えて、私はここを参照してください他の二つの問題があります:

  • 機能Tank_Shape_Calcsのすべての呼び出し中にswitcherの再定義は、これは一般的に良いアイデアではありません。それらのほんの一握りが必要になることがありますときに我々が*args何の私の理解であれば

:-)を持っている理由です、(原因positionalsとしてその定義に)すべての引数がを渡すことが を要求
  • 「正しいまで再、私はTank_Shapefunctionへのオブジェクトのマッピングとして、関数の外スイッチャーを移動したい:

    switcher = { 
        0: vertical.Vertical_Tank, 
        1: horiz.Horiz_Cylinder_Dished_Ends, 
        2: strapping.Calc_Strapped_Volume, 
        3: poly.Fifth_Poly_Calcs 
    } 
    

    を次に、でタプルとして過剰の引数を取るようにTank_Shape_Calcsを定義します:

    def Tank_Shape_Calcs(Tank_Shape, *args): 
        return switcher.get(Tank_Shape, lambda *_: "ERROR: Tank type not valid")(*args) 
    

    .getの後に関数を呼び出します。

    lambda.getに定義することもできますが、多くのargs(結果的に無視される)で呼び出されるようにするには、*_を使用します。

  • +2

    ちょうど美しい! –

    +1

    @ Jean-FrançoisFabre私は何かを逃してしまう恐れがあることをまだ見ています。私がテストできる最小限の例は私の不安を払うものではないという事実です。 –

    +0

    私は理解しています。少なくともラムダは十分安全な修正です。 OPにあなたの解決策をテストさせてください。それがうまくいかない場合は、私は4つのアップフォートを撤回します:) –

    関連する問題