Я написал простой сценарий для решения «логической головоломки», типа головоломки из школы, где вам дают ряд правил, а затем необходимо найти решение для таких проблем, как «Есть пять музыкантов по имени А, 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) ...
?