有没有办法获得函数的返回值并同时测试它是“非零”?

时间:2012-04-28 01:16:33

标签: python

我的代码如下:

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等价物?

5 个答案:

答案 0 :(得分: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语句将失败。

答案 1 :(得分: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):
   #...

答案 2 :(得分: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;

答案 3 :(得分: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语句 - 或者调用你的函数两次!可能还有更复杂的组织方式 - 这实际上只是一个粗略的例子,说明你可以做些什么。例如,您可能能够创建一个满载(priority, test_func, handler_func)元组的已排序容器并对其进行迭代。

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

答案 4 :(得分: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)

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