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-style 方法。如果你需要修改很多本地状态,使用一个类和方法。(如果没有,只需使用函数;但我会在这里假设类案例。)所以像这样:

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语句 - 或调用您的函数两次!可能还有更复杂的方法来组织上述内容 - 这实际上只是您可以做的一个粗略示例。例如,您可能能够创建一个充满(priority, test_func, handler_func)元组的排序容器并对其进行迭代。

无论如何,我认为你应该考虑重构这个长长的if/elif子句列表。

于 2012-04-28T02:11:53.183 回答
0

您可以获取函数列表,使其成为生成器并返回第一个 Truey 函数:

functions = [func_cliche_start, func_test_start, func_macro_start]
functions_gen = (f(line) for f in functions)
a = next((x for x in functions_gen if x), None)

仍然看起来有点奇怪,但重复性要少得多。

于 2013-06-06T14:25:02.003 回答