是否有Python惯用法来评估带有短路的功能/表达式列表? [英] Is there a Python idiom for evaluating a list of functions/expressions with short-circuiting?
问题描述
我写了一个简单的脚本来解决逻辑难题",这是学校给出的一些规则的难题,然后必须能够找到问题的解决方案,例如有五位音乐家名叫A, B,C,D和E在一场音乐会中演奏,彼此依次演奏...如果A在B之前,而D不是最后一个……谁在什么时候演奏的顺序是什么?"等
I wrote a simple script to solve a "logic puzzle", the type of puzzle from school where you are given a number of rules and then must be able to find the solution for problems like "There are five musicians named A, B, C, D, and E playing in a concert, each plays one after the other... if A goes before B, and D is not last ... what is the order of who plays when?" etc.
为了评估可能的解决方案,例如,我将每个规则"编写为单独的函数,以评估可能的解决方案(简单地表示为字符串列表)是否有效
To evaluate possible solutions, I wrote each "rule" as a separate function which would evaluate if a possible solution (represented simply as a list of strings) is valid, for example
#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...
我有兴趣寻找一种Python方法来测试可能的解决方案是否通过所有此类规则,并能够在第一个失败后停止评估规则.
I'm interested in finding the Pythonic way to test if a possible solution passes all such rules, with the ability to stop evaluating rules after the first has failed.
起初,我写了最简单的东西:
At first I wrote the simplest possible thing:
def is_valid(solution):
return rule1(solution) and rule2(solution) and rule3(solution) and ...
但这看起来很丑.我以为我可以用列表理解之类的东西使读起来更优雅一些.
But this seemed rather ugly. I thought perhaps I could make this read a bit more elegant with something like a list comprehension...
def is_valid(solution)
rules = [rule1, rule2, rule3, rule4, ... ]
return all([r(solution) for f in rules])
...但是我意识到,由于列表理解是在评估all()
函数之前生成的,因此具有完全没有短路的副作用-即使第一个规则都会被评估.返回False
.
... but then I realized that since the list comprehension is generated before the all()
function is evaluated, that this has the side effect of not being short-circuited at all - every rule will be evaluated even if the first returns False
.
所以我的问题是:有没有更多的Pythonic/函数式方法可以评估True
/False
表达式列表,而又无需短路,而无需写出很长的
So my question is: is there a more Pythonic/functional way to be able to evaluate a list of True
/False
expressions, with short-circuiting, without the need to write out a long list of return f1(s) and f2(s) and f3(s) ...
?
推荐答案
使用生成器表达式:
rules = [ rule1, rule2, rule3, rule4, ... ]
rules_generator = ( r( solution ) for r in rules )
return all( rules_generator )
语法糖:您可以省略多余的括号:
Syntactic sugar: you can omit the extra parentheses:
rules = [ rule1, rule2, rule3, rule4, ... ]
return all( r( solution ) for r in rules )
生成器(基本上)是具有.next()
方法的对象,该方法以某种可迭代的方式返回下一项.这意味着他们可以做一些有用的事情,例如读取块中的文件而无需将其全部加载到内存中,或者迭代到巨大的整数.您可以透明地使用for
循环遍历它们. Python在后台处理它.例如,range
是Py3k中的生成器.
A generator is (basically) an object with a .next()
method, which returns the next item in some iterable. This means they can do useful things like read a file in chunks without loading it all into memory, or iterate up to huge integers. You can iterate over them with for
loops transparently; Python handles it behind-the-scenes. For instance, range
is a generator in Py3k.
您可以使用yield
语句而不是函数定义中的return
来滚动自己的自定义生成器表达式:
You can roll your own custom generator expressions by using the yield
statement instead of return
in a function definition:
def integers():
i = 0
while True:
yield i
,Python将处理保存函数的状态,依此类推.他们太棒了!
and Python will handle saving the function's state and so on. They're awesome!
这篇关于是否有Python惯用法来评估带有短路的功能/表达式列表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!