我写了一个简单的脚本来解决一个“逻辑谜题”,这是一种来自学校的谜题类型,您可以在其中获得许多规则,然后必须能够找到问题的解决方案,例如“有五个音乐家名为A,B ,C,D和E在一场音乐会中演奏,每一个都依次演奏......如果A在B之前,而D不是最后......谁在什么时候演奏?等是否有Python语言用于评估短路的函数/表达式列表?
评估可能的解决方案,我写的每一个“规则”作为一个独立的功能,如果可能的解决方案(简单地表示为一个字符串列表)是有效的,其将评估,例如
#Fifth slot must be B or D
def rule1(solution):
return solution[4] == 'B' or solution[4] == 'D'
#There must be at least two spots between A and B
def rule2(solution):
returns abs(solution.index('A') - solution.index('B')) >= 2
#etc...
我对寻找Pythonic方法感兴趣,以测试一个可能的解决方案是否通过了所有这些规则,并能够在第一个失败后停止评估规则。
起初,我写了简单的方式就是:
def is_valid(solution):
return rule1(solution) and rule2(solution) and rule3(solution) and ...
但这似乎相当难看。我想也许我能做出这样读的东西,如一个列表理解多一点优雅......
def is_valid(solution)
rules = [rule1, rule2, rule3, rule4, ... ]
return all([r(solution) for f in rules])
...但后来我意识到,自从all()
功能之前生成的列表中理解评估,即这具有根本不会短路的副作用 - 即使第一个返回False
,也将评估每个规则。
所以我的问题是:是否有一个更Python /功能性的方式才能够评估True
/False
表情列表,以及短路,而不需要写出来的return f1(s) and f2(s) and f3(s) ...
一个长长的清单?
所以这里的基本区别是省略了'return all([r(solution)for r in rules])'中的括号,因此在'all()'被评估之前不会创建所有结果的列表? – 2010-08-04 13:16:10
是的。在这两种情况下,“all”的参数在传递之前进行评估,但评估列表理解会在内存中创建整个列表,而评估生成器表达式会创建一个生成器对象,该对象根据需要加载元素。 – katrielalex 2010-08-04 13:19:21
完美,这使得很多感 - 感谢 – 2010-08-04 13:23:47