我有大约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时有重复,我可以在函数中拉这个登录!但还有其他更清洁的解决方案吗?
我可以考虑将函数放在数据结构中并循环调用它们。
答案 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)
我可以考虑将函数放在数据结构中并循环调用它们。
是的,可能你应该这样做,因为你的代码需要重构,
数据驱动设计是一个不错的选择。
# 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中,我认为你应该继续使用函数列表和循环。