Как «и» и «или» работают, когда объединены в одном утверждении? - PullRequest
7 голосов
/ 05 апреля 2010

Почему-то эта функция меня смутила:

def protocol(port):
    return port == "443" and "https://" or "http://"

Может кто-нибудь объяснить порядок происходящего за сценой, чтобы заставить эту работу работать так, как она делает.

Я понял это, пока не попробовал:

Либо А)

def protocol(port):
    if port == "443":
        if bool("https://"):
            return True
    elif bool("http://"):
        return True
    return False

или B)

def protocol(port):
    if port == "443":
        return True + "https://"
    else:
        return True + "http://"

Это какой-то особый случай в Python или я совершенно не понимаю, как работают операторы?

Ответы [ 7 ]

24 голосов
/ 05 апреля 2010

Это старая идиома; вставка скобок для отображения приоритета,

(port == "443" and "https://") or "http://"

x and y возвращает y, если x верно, x, если x неверно; a or b, наоборот, возвращает a, если это верно, в противном случае b.

Таким образом, если port == "443" истинно, это возвращает RHS and, то есть "https://". В противном случае and ложно, поэтому or входит в игру и возвращает "" http://", его RHS.

В современном Python лучший способ перевести этот старый идиом:

"https://" if port == "443" else "http://"
8 голосов
/ 05 апреля 2010

and возвращает правый операнд, если левый равен true. or возвращает правый операнд, если левый - ложь. В противном случае они оба возвращают левый операнд. Говорят, что они объединяются .

5 голосов
/ 05 апреля 2010

C and X or Y - это длительная ранняя попытка пользователей Python прокси для C ? X : Y

По большей части это работает, за исключением , если X равно False - это привело ко многим ошибкам в коде Python, поэтому в Python FAQ вы Вы найдете более правильное решение: (C and [X] or [Y])[0], потому что список с одним элементом, независимо от его оцененного логического значения, всегда равен True! Например: [None] - это True, а None - нет. Приведенный выше пример OP работает, потому что строка, представляющая X, не является пустой.

Однако все это изменилось в Python 2.5, когда к языку был добавлен троичный или условный оператор, что позволило вам использовать очиститель X if C else Y, как указано в других публикациях здесь. Если вы видите код, использующий старый формат, то это потому, что пользователь долгое время был программистом Python, который еще не принял новый синтаксис, он вырезал и вставлял другой старый код, или его работодатель все еще использует 2.4.x ( или более ранние выпуски) и т. д.

2 голосов
/ 05 апреля 2010

Это уродливый хак, который не рекомендуется. Это работает из-за короткого замыкания and и or и того, что они возвращают один из своих аргументов, а не логическое значение. Использование этой техники может привести к появлению труднодоступных ошибок, поэтому не используйте его в новом коде.

Вот пример того, как идиома and/or может дать неожиданный результат:

>>> foo = 'foobar'
>>> bar = 'foobar'
>>> x = 0
>>> y = 1
>>> (foo == bar) and x or y   # Will this return the value of x if (foo == bar)?
1

Вместо этого предпочитайте более новые обозначения:

return "https://" if port == "443" else "http://"
1 голос
/ 05 апреля 2010

Возможно, вы захотите прочитать о «и / или уловке» Python в этой статье Своеобразная природа И и Или в Python . Это немного похоже на IIF() в VBA или VB или ?: в языках стиля C.

0 голосов
/ 02 августа 2017

При всех хороших ответах я обнаружил, что эти высказывания помогают мне лучше запомнить это и соответствуют тому, как работает мой мозг (и, надеюсь, еще для чего-то там):

  • «and» возвращает первый ложный элемент (например, None, «», [], (), {}, 0) или последний элемент, если его нет (например, False найден)

  • «или» возвращает первый истинный элемент или последний элемент (например, истинный элемент не найден) **

В итоге :

  • все они возвращают первый элемент, который решает исход заявления. (В худшем случае последний элемент в последовательности)

Обратите внимание, что это правило также применяется к цепочечной инструкции "и" или всем "или"

0 голосов
/ 05 апреля 2010

Эта конструкция работает, потому что она "разворачивается" в следующий код:

а и б ->

if a:
  return b
else:
  return a

а или б ->

if a:
  return a
else:
  return b
...