How do “and” and “or” work when combined in one statement?

夙愿已清 提交于 2019-11-28 10:17:29

It's an old-ish idiom; inserting parentheses to show priority,

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

x and y returns y if x is truish, x if x is falsish; a or b, vice versa, returns a if it's truish, otherwise b.

So if port == "443" is true, this returns the RHS of the and, i.e., "https://". Otherwise, the and is false, so the or gets into play and returns `"http://", its RHS.

In modern Python, a better way to do translate this old-ish idiom is:

"https://" if port == "443" else "http://"

and returns the right operand if the left is true. or returns the right operand if the left is false. Otherwise they both return the left operand. They are said to coalesce.

C and X or Y is the long-running early attempt by Python users to proxy for C ? X : Y

For the most part it works, except if X is False -- this has led to many bugs in Python code, so in the Python FAQ, you'll find the more correct solution being (C and [X] or [Y])[0] because a list with a single element, regardless of its evaluated Boolean value, is always True! For example: [None] is True but None isn't. The OP's example above works because the string representing X is not empty.

However, all this changed in Python 2.5, when the ternary or conditional operator was added to the language, allowing you to use the cleaner X if C else Y as stated in other posts here. If you see code using the older format, it's because the user has been a long time Python programmer who hasn't adopted the new syntax yet, they cut-n-paste other old code, or their employer is still using 2.4.x (or earlier releases), etc.

This is an ugly hack that is not recommended. It works because of the short-circuiting behaviour of and and or and that they return the one of their arguments rather than a boolean value. Using this technique gives a risk of introducing hard-to-find bugs, so don't use it in new code.

Here's an example of how the and/or idiom can give an unexpected result:

>>> 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

Prefer instead the newer notation:

return "https://" if port == "443" else "http://"
Abel

You may want to read up on the "and / or trick" of Python in this article The Peculiar Nature of And and Or in Python. It's a bit like the IIF() in VBA or VB, or ?: in C-style languages.

This construction works because it 'unfolds' to the following code:

a and b -->

if a:
  return b
else:
  return a

a or b -->

if a:
  return a
else:
  return b

With all the good answers, I found these statements help me remember this better and fit how my brain works (and hopefully for for some more out there) :

  • “and" returns the first False item (e.g., None, “”, [], (), {}, 0) or the last item if none (e.g. no False found)

  • “or" returns the first True item or the last item (e.g. no True found)**

In summary:

  • they all return the first item that decides the outcome of the statement. (In the worst case, the last item in the sequence)

Note this rule also applies to a chained all "and" or all "or" statement

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!