Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/343.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如果让代码看起来难看,还有更干净的解决方案吗?_Python - Fatal编程技术网

Python 如果让代码看起来难看,还有更干净的解决方案吗?

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

我有大约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 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