if else-如果使代码看起来丑陋任何更清洁的解决方案?

时间:2010-05-05 19:21:07

标签: python

我有大约20个函数(is_func1,is_fucn2,is_func3 ...)返回布尔值

我假设只有一个函数返回true,我想要那个!

我在做:

if is_func1(param1, param2):
    # I pass 1 to following
    abc(1) # I pass 1
    some_list.append(1)
elif is_func2(param1, param2):
    # I pass 2 to following
    abc(2) # I pass 1
    some_list.append(2)
...
.
.
elif is_func20(param1, param2):
...

请注意:param1和param2各有不同,abc和some_list取决于函数的参数。

代码看起来很大,并且在调用abc和some_list时有重复,我可以在函数中拉这个登录!但还有其他更清洁的解决方案吗?

我可以考虑将函数放在数据结构中并循环调用它们。

9 个答案:

答案 0 :(得分:4)

怎么样?
functionList = [is_func1, is_func2, ..., is_func20]
for index, func in enumerate(functionList):
    if(func(param1, param2)):
        abc(index+1)
        some_list.append(index+1)
        break

答案 1 :(得分:2)

  

我可以考虑将函数放在数据结构中并循环调用它们。

是的,可能你应该这样做,因为你的代码需要重构,
数据驱动设计是一个不错的选择。

类似于BlueRaja's answer

的示例
# arg1, arg2 and ret can have any values on each record
data = ((isfunc1, arg1, arg2, ret),
 (isfunc2, arg1, arg2, ret),
 (isfunc3, arg1, arg2, ret),
  ...)

for d in data:
    if d[0](d[1], d[2]):
        abc(d[3])
        some_list.append(d[3])
        break

答案 2 :(得分:1)

如果您的事件调度程序的每个分支实际上都是不同的,那么就没有办法绕过编写各个分支处理程序,并且没有任何方法可以绕过不同的情况并选择分支

答案 3 :(得分:1)

试试这个:

value = 1 if is_func1(param1, param2) else \
        2 if is_func2(param1x, param2x) else \
        ... else \
        20 if is_func20(param1z, param2z) else 0

abc(value)
some_list.append(value)

请记住,这个声明是使用各种网站拼凑在一起作为Python语法的参考,所以如果它不编译,请不要拍我。

基本要点是生成一个与所调用函数对应的单个值(1表示is_func1,2表示is_func2,等等)然后在abc中使用该值some_list.append功能。继续我能够阅读的有关Python布尔表达式求值的内容,这应该正确地使评估短路,以便在评估为true时立即停止调用函数。

答案 4 :(得分:1)

这似乎是应用Chain of responsibility pattern的好例子。

我知道如何用对象给出示例,而不是函数,所以我会这样做:

class HandleWithFunc1
   def __init__(self, otherHandler):
      self.otherHandler = otherHandler

   def Handle(param1, param2):
     if ( should I handle with func1? ):
          #Handle with func1
          return
     if otherHandler == None:
        raise "Nobody handled the call!"

     otherHandler.Handle(param1, param2)

class HandleWithFunc2:
   def __init__(self, otherHandler):
      self.otherHandler = otherHandler

   def Handle(param1, param2):
     if ( should I handle with func1? ):
          #Handle with func1
          return
     if otherHandler == None:
        raise "Nobody handled the call!"

     otherHandler.Handle(param1, param2)

所以你创建了所有的类,如链:

handle = HandleWithFunc1(HandleWithFunc2())

然后:

handle.Handle(param1, param2)

此代码易于重构,此处仅用于说明用法

答案 5 :(得分:1)

我为不同的参数修改了BlueRaja答案......

function_list = {is_func01: (pa1, pa2, ...),
                 is_func02: (pa1, pa2, pa3, ...), 
                 ....
                 is_func20: (pa1, ...)}

for func, pa_list in function_list.items:
    if(func(*pa_list)):
        abc(pa_list_dependent_parameters)
        some_list.append(pa_list_dependent_parameters)
        break

我不明白为什么它不起作用。

答案 6 :(得分:0)

之前我没有使用过python,但你可以通过变量来引用函数吗?

如果是这样,你可以创建一个带有表示每个函数的条目的枚举,测试循环中的所有函数,并将变量设置为'true'函数的枚举。

然后你可以在枚举上做一个switch语句。

但是,这不会“清理”代码:当你有n个选项并需要驱动到正确的代码时,你需要n块代码来处理它。

答案 7 :(得分:0)

我不确定它是否更干净,但我认为这是非常有趣的解决方案。

首先,您应该定义新功能,让它为semi_func,它会调用abc,而some_list.append会使代码DRY。

然后设置新变量作为所有布尔函数的二进制结果,因此is_func1是它的第20位,is_func2是19,依此类推。 32位整数类型应该足以处理所有20个结果。

在为此结果变量设置值时,您应该使用shift left来添加新函数:

result = is_func1(param1, param2) << 1
result = (result | is_func2(param1, param2)) << 1
...
result = (result | is_func20(param1, param2))

为方便访问,定义新的常量,如

IS_FUNC20_TRUE = 1
IS_FUNC19_TRUE = 2
IS_FUNC18_TRUE = 4
... values should be powers of 2

最后使用switch / sase语句来调用semi_func

答案 8 :(得分:-3)

我知道我会因为非正式而受到限制,但仍然存在。如果您发现任何可以使用标准控件构造进行的操作,那么您需要使用不同的语言,例如Common Lisp,它允许使用宏,实际上可以创建自己的控件构造。 (最近发现了一个照应宏,我只需要推荐它。)

这个具体案例将是一个完美的例子,宏可以提供帮助,但只假设您在代码中的多个位置执行此操作,否则根本不值得改进。事实上,Common Lisp已经有了这样的宏,它被称为 cond

无论如何,在Python中,我认为你应该继续使用函数列表和循环。