Python 如果让代码看起来难看,还有更干净的解决方案吗?
我有大约20个函数(is_func1,is_func2,is_func3…)返回布尔值 我假设只有一个函数返回true,我希望如此 我正在做:Python 如果让代码看起来难看,还有更干净的解决方案吗?,python,Python,我有大约20个函数(is_func1,is_func2,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 p
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和某些_列表根据功能采用参数
代码看起来很大,在调用abc和一些列表时有重复,我可以在函数中拉这个登录!但还有其他更清洁的解决方案吗
我可以考虑将函数放在数据结构中并循环调用它们。我以前没有使用python,但是您能通过变量引用函数吗 如果是这样,您可以创建一个包含代表每个函数的条目的枚举,测试循环中的所有函数,并将变量设置为“true”函数的枚举 然后可以在枚举上执行switch语句
不过,这并不能“清理”代码:当您有n个选项并且需要向下驱动到正确的选项时,您将需要n个代码块来处理它。如果您的事件分派器的每个分支实际上都不同,那么就没有办法绕过编写各个分支处理程序,没有任何方法可以绕过轮询不同的案例和选择分支。尝试以下方法:
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
和某些函数列表中使用该值。追加函数。继续我读到的关于Python布尔表达式求值的内容,这应该适当地缩短求值,以便在求值为true时停止调用函数。这看起来是一个很好的应用案例
我知道如何使用对象而不是函数给出示例,因此我将这样做:
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())
然后:
这段代码容易重构,这里只是为了说明它的用法
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
我知道我会因为离题而被调侃,但仍然如此。如果您发现任何可以用标准控件构造完成的事情都令人不快,那么您需要使用另一种语言,例如Common Lisp,它允许使用宏,实际上可以创建您自己的控件构造。(由于最近发现了回指宏,我只能推荐这个。)
这个特定的例子将是一个完美的例子,其中一个宏将有所帮助,但只假设您在代码中的多个位置执行它,否则它可能根本不值得改进。事实上,Common Lisp已经有了这样一个宏,叫做cond
无论如何,在Python中,我认为您应该使用函数列表和循环。我不确定它是否更干净,但我认为这是一个非常有趣的解决方案
首先,您应该定义新函数,让它成为semi_func
,它将调用abc
和一些列表。追加
使代码干燥
然后设置新变量作为所有布尔函数的二进制结果,使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))
最后使用switch/sase语句调用semi_func
我可以考虑将函数放入数据结构并循环调用它们
是的,可能您应该这样做,因为您的代码需要重构,
数据驱动设计是一个不错的选择
一个类似的例子
我为不同的参数修改了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
我不明白为什么它不应该工作。函数在内部是什么样子的?你能用更真实的代码更新一下吗?例如,你在便笺中说param1
和param2
是不同的,但你显示的是相同的。有这样的函数吗?Is_funcN(param3,param4,param5):
?@Fletcher:里面是一个复杂的表达式,计算结果是boolean@Oscar:All函数接受两个参数,每个参数都可能不同。如果在适当的分派索引后面写一个switch()线性搜索,则不会真正获得任何结果在调度索引上。在这种情况下,你最好咬紧牙关,同意吗,但这可能比将所有函数调用都放在if/else树中要好。函数是Python中的第一类。我不确定他在多大程度上用伪名称替换了代码,但看起来他可能会更枯燥。我认为如果函数采用不同的参数,会有问题。@Oscar:True,但那将是一个不同的问题,有不同的答案。答:我并没有完全理解这个问题,它说:请注意:param1和param2各不相同。我在OPIf中添加了一条注释,如果参数不同,亚当的答案可能是最好的。我发布了一个对你的代码的修改,它应该对每个函数使用不同的参数;不适用于非主题-问题不在于标准控件,而在于代码的重复。如果可以的话,我会再次-1,因为我建议使用宏。@BlueRaja。。。让我来做吧,但我的目的是为了在原始帖子中发布一个答案,而这可能是一个完美的评论。BlueRaja-你知道Common Lisp吗?你自相矛盾。几乎任何代码的重复都可以通过使用合适的宏轻松解决,这并不是一件坏事。如果你不知道我的意思,请阅读优秀书籍《实用通用Lisp》的第3章。然后,下一个可怜的笨蛋开始在应用程序中搜索所有不同的处理程序,并开始自己弄清楚
IS_FUNC20_TRUE = 1
IS_FUNC19_TRUE = 2
IS_FUNC18_TRUE = 4
... values should be powers of 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
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