Python: избегайте оценки короткого замыкания
Это проблема, которая возникла у меня во время работы над проектом Django. Это о проверке формы.
В Django, когда у вас есть представленная форма, вы можете вызвать is_valid()
в соответствующем объекте формы, чтобы вызвать проверку и вернуть логическое значение. Таким образом, обычно у вас есть такой код внутри функций просмотра:
if form.is_valid():
# code to save the form data
is_valid()
не только проверяет данные формы, но также добавляет сообщения об ошибках в объект формы, который впоследствии может быть отображен пользователю.
На одной странице я использую две формы вместе, а также хочу, чтобы данные сохранялись, только если обе формы содержат достоверные данные. Это означает, что я должен вызвать is_valid() в обеих формах перед выполнением кода для сохранения данных. Наиболее очевидный способ:
if form1.is_valid() and form2.is_valid():
# ...
не будет работать из-за оценки коротких замыканий логических операторов. Если form1 недействителен, form2 не будет оцениваться и его сообщения об ошибках будут отсутствовать.
Это только пример. Насколько мне известно, нет никакой жадной альтернативы and
/or
, как на других языках (т.е. Smalltalk). Я могу представить, что проблема возникает при разных обстоятельствах (и не только в Python). Решения, о которых я мог думать, - все это неудобные (вложенные ifs, присваивающие возвращаемые значения локальным переменным и использующие их в выражении if). Я хотел бы знать питоновский способ решения таких проблем.
Спасибо заранее!
Ответы
Ответ 1
Как насчет чего-то типа:
if all([form1.is_valid(), form2.is_valid()]):
...
В общем случае можно использовать понимание списка, поэтому результаты вычисляются спереди (в отличие от выражения генератора, которое обычно используется в этом контексте). например:.
if all([ form.is_valid() for form in (form1,form2) ])
Это будет хорошо масштабироваться и для любого количества условий... Единственный улов в том, что все они должны быть подключены с помощью "and
", а не if foo and bar or baz: ...
.
(для короткого замыкания or
вы можете использовать any
вместо all
).
Ответ 2
Вы можете просто использовать двоичный оператор &
, который будет выполнять логику AND без необходимости короткого замыкания на bools.
if form1.is_valid() & form2.is_valid():
...