Я написал простой сценарий для решения «логической головоломки», типа головоломки из школы, где вам дается ряд правил, а затем вы должны быть в состоянии найти решение для таких задач, как «Есть пять музыкантов по имени A, B, C , D и E, играющие на концерте, играют друг за другом... если A идет перед B, а D не последним... в каком порядке кто и когда играет?" и т.п.
Чтобы оценить возможные решения, я написал каждое «правило» как отдельную функцию, которая будет оценивать, допустимо ли возможное решение (представленное просто как список строк), например
#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
.
Итак, мой вопрос: есть ли более Pythonic/функциональный способ оценить список выражений True
/False
с коротким замыканием, без необходимости выписывать длинный список return f1(s) and f2(s) and f3(s) ...
?