2

次のようなコードがあります。

if(func_cliche_start(line)):
   a=func_cliche_start(line)
   #... do stuff with 'a' and line here
elif(func_test_start(line)):
   a=func_test_start(line)
   #... do stuff with a and line here
elif(func_macro_start(line)):
   a=func_macro_start(line)
   #... do stuff with a and line here
...

各 func_blah_start 関数は、(入力行に基づいて) None または文字列を返します。func_blah_start の冗長な呼び出しは無駄に思えるので好きではありません (func_blah_start は「純粋」であるため、副作用はないと想定できます)。この種のより良いイディオムはありますか、またはそれを行うためのより良い方法はありますか?

おそらく私は間違っています (私の C は錆びています) が、C でこれを行うことができると思いました:

int a;
if(a=myfunc(input)){ /*do something with a and input here*/ }

pythonに相当するものはありますか?

4

5 に答える 5

4

if 文の前に関数 func_cliche_start を変数 a に代入しませんか?

a = func_cliche_start(line)
if a: 
   pass  # do stuff with 'a' and line here

func_cliche_start(line) が None を返す場合、if ステートメントは失敗します。

于 2012-04-28T01:20:15.500 に答える
3

これを機能させるラッパー関数を作成できます。

def assign(value, lst):
    lst[0] = value
    return value

a = [None]
if assign(func_cliche_start(line), a):
   #... do stuff with 'a[0]' and line here
elif assign(func_test_start(line), a):
   #...
于 2012-04-28T01:27:14.513 に答える
2

処理関数をループするだけで、より簡単で行数が少なくなります:)、ケースごとに異なることをしたい場合は、それを関数でラップして呼び出します。

for func, proc in [(func_cliche_start, cliche_proc), (func_test_start, test_proc), (func_macro_start, macro_proc)]:
    a = func(line)
    if a:
        proc(a, line)
        break;
于 2012-04-28T01:29:11.353 に答える
0

これらのコード ブロックを関数に配置する必要があると思います。そうすれば、dispatcherスタイルのアプローチを使用できます。多くのローカル状態を変更する必要がある場合は、クラスとメソッドを使用してください。(そうでない場合は、関数を使用してください。ただし、ここではクラスのケースを想定します。)したがって、次のようになります。

from itertools import dropwhile

class LineHandler(object):
    def __init__(self, state):
        self.state = state
    def handle_cliche_start(self, line):
        # modify state
    def handle_test_start(self, line):
        # modify state
    def handle_macro_start(self, line):
        # modify state

line_handler = LineHandler(initial_state)
handlers = [line_handler.handle_cliche_start,
            line_handler.handle_test_start,
            line_handler.handle_macro_start]
tests = [func_cliche_start, 
         func_test_start, 
         func_macro_start]
handlers_tests = zip(handlers, tests)

for line in lines:
    handler_iter = ((h, t(line)) for h, t in handlers_tests)
    handler_filter = ((h, l) for h, l in handler_iter if l is not None)
    handler, line = next(handler_filter, (None, None))
    if handler:
        handler(line)

これは元のコードよりも少し複雑ですが、よりスケーラブルな方法で物事を区分していると思います。関数の並列リストを個別に維持する必要がありますが、長いifステートメントを記述したり、関数を 2 回呼び出したりすることなく、必要なだけ追加できるというメリットがあります。上記を整理するためのより洗練された方法もおそらくあるでしょう。たとえば、(priority, test_func, handler_func)タプルでいっぱいの並べ替えられたコンテナーを作成し、それを反復処理できる場合があります。

ifいずれにせよ、この/elif句の長いリストをリファクタリングすることを検討する必要があると思います。

于 2012-04-28T02:11:53.183 に答える