Страницы

Поиск по вопросам

четверг, 11 апреля 2019 г.

Почему False and str возвращает False, но True and str возвращает str?

Понимаю, что в Python применются ленивые вычисления, но мне кажется это настоящие грабли. Вот реальный пример: (sqlalchemy_migrate)
funcname = upgrade and "upgrade" or "downgrade"
То есть в зависимости от значения upgrade (True или False), переменная получит соответствующее имя. С ходу довольно сложно понять, что вернет такое выражение. Кроме того, bool and str может вернуть как bool, так и str, в зависимости от того, чему равен bool. Считаете ли вы такой подход рациональным?


Ответ

Насколько я понимаю, у Вас нет вопроса, как именно вычисляется выражение в примере, но все же напишу. Т.к. приоритет and и or одинаков, и эти операторы левоассоциативны, то
upgrade and "upgrade" or "downgrade"
эквивалентно
(upgrade and "upgrade") or "downgrade"
Первым вычисляем выражение в скобках, оно равно False если upgrade == False(1), или "upgrade", если upgrade == True(2). В итоге имеем
(1) False or "downgrade" --> "downgrade" (2) "upgrade" or "downgrade" --> "upgrade" (т.к. "upgrade" - истинно)

П.С. Лично мне именно эта строчка также кажется не слишком читаемой. Вообще, здесь явно напрашивается использование тернарного оператора, который имеется в Питоне, хотя и синтаксически отличается от тернарного оператора в большинстве других языков:
funcname = "upgrade" if upgrade else "downgrade"
Это всего на один символ длиннее, но бывают случаи, когда подобная запись действительно удобна и читаема:
do_something() or do_something_else()
do_something_else выполнится только в том случае, если do_something вернет False (например, что-то пошло не так). Это, фактически, стандартная идиома для языка perl, в Питоне я что-то подобное встречал значительно реже.

Комментариев нет:

Отправить комментарий