Как и и или работают, когда объединены в одном утверждении?

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

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

Or B)

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

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


person orokusaki    schedule 05.04.2010    source источник
comment
@Responders, посмотрите мое обновление через 1 минуту. Извиняюсь.   -  person orokusaki    schedule 05.04.2010
comment
Просто помните, что операторы «и» и «или» возвращают последнее вычисляемое выражение. :)   -  person João Portela    schedule 05.04.2010


Ответы (7)


Это старая идиома; вставка круглых скобок, чтобы показать приоритет,

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

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

Итак, если port == "443" истинно, это возвращает правую часть and, т. е. "https://". В противном случае and является ложным, поэтому or вступает в игру и возвращает `"http://", его правую сторону.

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

"https://" if port == "443" else "http://"
person Alex Martelli    schedule 05.04.2010
comment
@Alex +1 Спасибо за подробное объяснение. Они, видимо, сделали так, что я не могу принять ответ в течение 10 минут :( но отличный ответ. - person orokusaki; 05.04.2010
comment
@orokusaki, спасибо, и я уверен, что вы сможете принять это позже ;-). - person Alex Martelli; 05.04.2010
comment
+1 за упоминание тернарного оператора python, гораздо легче читать/понимать imho - person tosh; 05.04.2010
comment
Я давно научился использовать круглые скобки, чтобы заставить интерпретатор/компилятор делать то, что я хочу от кода, а не зависеть от приоритета. Это помогает документировать код для меня и всех, кто его поддерживает после того, как я его передал. Я считаю это частью защитного кодирования. - person the Tin Man; 05.04.2010

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

person Ignacio Vazquez-Abrams    schedule 05.04.2010
comment
А, спасибо, Игнасио. Я не знаю, как я зашел так далеко в Python, не понимая этого. Я впервые вижу, чтобы его использовали именно так. +1 - person orokusaki; 05.04.2010

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

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

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

person wescpy    schedule 05.04.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://"
person Mark Byers    schedule 05.04.2010
comment
@Mark Это версия, с которой я знаком, и я никогда не видел версию в своем посте до сегодняшнего дня. +1 - person orokusaki; 05.04.2010

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

person Abel    schedule 05.04.2010
comment
@Абель Спасибо. Только что прочитал, интересная статья. Я много раз использовал синтаксис return a or b, но по какой-то причине этот фрагмент не работает. - person orokusaki; 05.04.2010

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

а и б -->

if a:
  return b
else:
  return a

a or b -->

if a:
  return a
else:
  return b
person Yaroslav    schedule 05.04.2010

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

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

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

Подводя итоги:

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

Обратите внимание, что это правило также применяется к цепочке операторов all "and" или all "or".

person Zhenhua    schedule 01.08.2017