我写了一个简单的脚本来解决逻辑难题",这是学校给出的一些规则的难题,然后必须能够找到问题的解决方案,例如有五位音乐家名叫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惯用法来评估带有短路的功能/表达式列表?
发布评论