Какой эффект имеет выражение типа "var" и "do_something_with (var)" в Python?
При поиске некоторых ответов в исходном коде пакета (дуршлаг будет конкретным) я наткнулся на строку, которую я не могу понять. Кроме того, мой PyCharm нахмурился: "выражение, похоже, не имеет эффекта".
Вот тезис кода:
...
for path in e.paths():
keyparts = []
msgs = []
for exc in path:
exc.msg and msgs.extend(exc.messages()) # <-- what is that?
keyname = exc._keyname()
keyname and keyparts.append(keyname) # <-- and that
errors['.'.join(keyparts)] = '; '.join(interpolate(msgs))
return errors
...
Кажется, это очень pythonic, и я хочу осваивать его!
UPD. Итак, поскольку я вижу, что это вообще не pythonic - читаемость вредит ради сокращения.
Ответы
Ответ 1
Если ключевое имя оценивается как False, оператор and
немедленно возвращает false и не оценивает вторую часть. В противном случае он будет оценивать вторую часть (не в этом случае значение возврата). Таким образом, это в основном эквивалентно:
if keyname:
keyparts.append(keyname)
Я не уверен, что это очень pythonic, хотя, поскольку версия, которую я только что предложил, выглядела намного более читаемой (по крайней мере, для меня лично).
Ответ 2
and
и or
short-circuiting логические операторы; что означает, что, как только Python узнает, какой должен быть ответ, он перестает оценивать любые оставшиеся предложения.
В фрагменте, который вы отправили and
, используется для защиты функций .extend()
и .append()
- предположительно, автор не хочет публиковать, например, None
в списках.
Я обычно использую эту функцию в операторах if
:
if name and name[0] in ('Mr', 'Mrs', 'Ms'):
...
name
- возможно пустой список - если он пуст, name[0]
терпит неудачу с IndexError
, поэтому я охраняю его с помощью name and
- если name
пуст, name[0]
( и блок if
) не выполняются и ошибка устранена.
Это очень Pythonic функция.
Ответ 3
Так как в python первое выражение в выражении and
оценивается до второго, и интерпретатор выходит из оценки выражения and
, если первое выражение False
,
keyname and keyparts.append(keyname)
эквивалентно:
if keyname:
keyparts.append(keyname)