2017-09-20 13 views
0

私はこのようなケースの選択持っている機能の多くを実装する必要があります。昇給エラーの最後のステップの繰り返しを避けるし、印刷するどのような方法があり、「それを自分で繰り返してはいけない」によると入力が不正な場合の法的引数のリストの出力方法は?

def foo1(bar1): 
    if bar1 == 'A': 
     do something 
    elif bar1 == 'B': 
     do something 
    elif ... 
    ... 
    else: 
     raise ValueError('legal input of bar1 should be {}'.format(list_of_bar)) 

def foo2(bar2): 
    if bar2 == 'A': 
     do something 
    elif bar2 == 'B': 
     do something 
    elif ... 
    ... 
    else: 
     raise ValueError('legal input of bar2 should be {}'.format(list_of_bar)) 

''' 

を正しい議論のリスト?私はデコレータがこれを行うかもしれないと思ったが、それを作る方法を確かめなかった。前もって感謝します。

更新

inspectモジュールを使用して実装しました。しかし、私はまだいくつかのアドバイスや、より良いソリューション

import inspect 
from functools import wraps 
import re 

def test_none(func): 
    _code = inspect.getsource(func) 
    _list = re.findall(r'if (\w+) == (\w+)', _code) 
    assert all(_list[0][0] == name for name, case in _list) 
    _arg = _list[0][0] 
    _case = tuple(case for name, case in _list) 

    @wraps(func) 
    def wrapper(*args, **kwargs): 
     results = func(*args, **kwargs) 
     if results is None: 
      raise ValueError(
        'Legal value of \'{arg}\' should be anyone of {case}'.format(
        arg=_arg, case=_case)) 
     return results 
    return wrapper 

@test_none 
def foo(bar): 
    if bar == 0: 
     return 1 
    elif bar == 1: 
     return 2 

試験例を得ることができることを望む:

foo(3) 
ValueError: Legal value of 'bar' should be anyone of ('0', '1') 
+2

def foo(bar): def a(): print('a():') def b(): print('b():') def c(): print('c():') actions = {'A': a, 'B': b, 'C': c} if bar in actions: actions[bar]() else: raise ValueError('legal input of bar should be {}'.format(sorted(actions.keys()))) 

デモ「何かをする」、「何かをする」などをするために「B」を使います。 –

+0

しかし、辞書では、私は本当にデコレータや他の "黒い魔法"によって避けたい、最終的なエラーと印刷のステップを行う必要があります。 –

答えて

1

私は一般に「多くの場合」のパターンがより明確に辞書で発現していることがわかります。

ここでは、呼び出す関数がそれぞれ異なる場合がありますが、各値が返す整数またはその他のオブジェクトであればパターンが機能すると仮定します。

辞書は、異なるケースをコードの読者に明確かつコンパクトに知らせる。

CASES = { 
    'A': do_something, 
    'B': do_something_else, 
    ... 
} 

def foo(bar): 
    if bar not in CASES: 
     raise ValueError('legal input of bar should be {}'.format(list_of_bar)) 

    # do stuff 
    CASES[bar]() 

代わりに、「許してください、許可ではありません」パターンを使用することです。この特定のケースでは、それは上記のようにはっきりしていないことがわかります。

def foo(bar): 
    try: 
     func = CASES[bar] 
    except KeyError: 
     raise ValueError(...) 
    # do stuff 
    func() 

または別の方法として、辞書.get方法を使用しますが、再び、私はそれがこの特定のシナリオのための第一の方法のように明確ではないと思います。

def foo(bar): 
    func = CASES.get(bar) 
    if func is None: 
     raise ValueError(...) 
    # do stuff 
    func() 
+0

私はこれらのすべての反応が好きです。そして、それぞれのパラダイムには良いユースケースがあると思います。よくやった! –

+0

答えをありがとう。しかし、私が定義するfooのような機能がたくさんある場合は、全体構造のかなりの冗長性もあります。私は、 "foo"関数をraiseエラーステップなしで使用し、最後のステップで新しい関数を吐き出す方法があるかどうか疑問に思っていました。 –

1

このような何か、アクションに可能な入力をマッピングするために辞書を使用して:あなたは ` "A" を`マッピングし、何かを探している

>>> foo('A') 
a(): 
>>> foo('Z') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "x.py", line 15, in foo 
    raise ValueError('legal input of bar should be {}'.format(sorted(actions.keys()))) 
ValueError: legal input of bar should be ['A', 'B', 'C'] 
+0

はい辞書はこの場合非常にうまくいきます。申し訳ありませんが、明確に表現していないのですが、必要なのは最終的な "ValueErrorを上げる"ステップを避けることです。私はこのような構造を持つさまざまな機能を必要としているので、繰返しエラーと印刷手順を回避する方法があると考えていました。私はこれがいくつかのメタプログラミングを必要とするかもしれないと思った。 –