开发者

How do "and" and "or" work when combined in one statement? [duplicate]

开发者 https://www.devze.com 2022-12-26 06:27 出处:网络
This question already has answers here: Does Python have a ternary conditional operator? (30 answers) How do "and" and "or" act with non-boolean values?
This question already has answers here: Does Python have a ternary conditional operator? (30 answers) How do "and" and "or" act with non-boolean values? (8 answers) Closed 2 months ago.

For some reason this function confused me:

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

Can somebody explain the order of what's happening 开发者_JAVA技巧behind the scenes to make this work the way it does.

I understood it as this until I tried it:

Either A)

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://"

Is this some sort of special case in Python, or am I completely misunderstanding how statements work?


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://"


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

0

精彩评论

暂无评论...
验证码 换一张
取 消