3
votes
True and "asdf" or "qwer"

result => "asdf"

False and "asdf" or "qwer"

result => "qwer"

I can't understand how those things work. I thought that boolean operator on string would make type error, but it didn't. Is it something like predefined statement, for instance "a if b else c"?

6

6 Answers

5
votes

Python and and or operations stop when the answer is determined and return the value of the last object scanned. They do not return True or False. I love this feature and find myself using it all the time.

Since non-empty strings count as True

True and "asdf" or absolutely_anything_here_or_following

stops calculating when it hits the or because the answer is now determined (one of the or values is true), and returns the last thing it checked ("asdf"). No further operands are even inspected.

On the other hand, when

False and "asdf" or absolutely_anything_here

hits the or, it doesn't know the anwser yet so continues to the next operand. As long as absolutely_anything_here is the last operation, the answer is determined and the last thing scanned is returned.

3
votes

and and or work just like the familiar boolean operators - they return true if both of their operands are true and false if one of their operands are true, respectively.

They also short circuit, just like && and ||.

However, in Python, where anything can be interpreted as being True or False in a boolean context, there is an additional fact - it will return the first operand that evaluated to True or evaluated to False in a boolean context, when it has enough information to stop evaluation. (This is as opposed to constructing and returning a real boolean True or False.) This is okay to do because if it is boolean evaluated it will evaluate to the boolean it would have returned if not for this fact.

Thus (note that "" is evaluated to False in a boolean context):

>>> "" and "a"
''
>>> "a" and "b"
'b'
>>> "a" and ""
''
>>>


>>> "" or ""
''
>>> "a" or ""
'a'
>>> "" or "a"
'a'
>>> "a" or "b"
'a'

>>> "" or False
False
>>> "" or True
True

>>> False and ""
False
2
votes

Before the Python conditional operator:

>>> age=20
>>> 'legal' if age>=21 else 'not legal'
'not legal'

There used to be 'cargo code' as a work around based on indexing tuples:

>>> ('not legal','legal')[age>=21]
'not legal'
>>> age=22
>>> ('not legal','legal')[age>=21]
'legal'

You can disassemble the two alternatives that you posted to see what is happening under the hood:

>>> import dis
>>> def f():
...    x=True and "asdf" or "qwer"
...    y=False and "asdf" or "qwer"
... 
>>> dis.dis(f)
  2           0 LOAD_GLOBAL              0 (True)
              3 POP_JUMP_IF_FALSE       12
              6 LOAD_CONST               1 ('asdf')
              9 JUMP_IF_TRUE_OR_POP     15
        >>   12 LOAD_CONST               2 ('qwer')
        >>   15 STORE_FAST               0 (x)

  3          18 LOAD_GLOBAL              1 (False)
             21 POP_JUMP_IF_FALSE       30
             24 LOAD_CONST               1 ('asdf')
             27 JUMP_IF_TRUE_OR_POP     33
        >>   30 LOAD_CONST               2 ('qwer')
        >>   33 STORE_FAST               1 (y)
             36 LOAD_CONST               0 (None)
             39 RETURN_VALUE 

You can see the values you see pop'ing up to the value you are seeing. You can also look at the short circuiting behavior of boolean operators and see this is documented behavior.

0
votes

Object in python considered True of False(like, '', None)

The result of the boolean result rely on the last value that could determine the result.

print 'aa' and True

True

'aa' is True, but it can't determine the result, so the result turn to True

while

print True and 'aa'

'aa'

But operator or is different from operator and, see

print None and True

None

The first None is considered False, and it could determine the last result, so it print 'None'

while

print False or 'bb'

'bb'

because the first False cant determine the final result!

0
votes

First Example
Python scans and evaluates from left to right.

In your first example

True and "asdf" or "qwer"

evaluates to

"asdf" or "qwer"

Because a non-empty string is True, Python short circuits (ignores the second operand) and returns the first operand "asdf". Remember True or x will return True regardless of the value of x.

Second example

False and "asdf" or "qwer"

this evaluates to

False or "qwer"

This time we don't short circuit on the first operand (we don't have enough information yet), and Python needs to check the second operand qwer, which evaluates to True in a boolean context (remember it's not empty), and returns it.

0
votes

Order of operations for operators: --not is evaluated first; --and is evaluated next; --or is evaluated last. as per your question first "and" operator is evaluated since Since non-empty strings count as True. hence True and "asdf" becomes True than True or "qwer" also becomes true. SO result becomes "asdf" In second False and "asdf" becomes false and false and "qwer" becomes false. hence it is false so it return last thing it has checked "qwer".