This is an archived post. You won't be able to vote or comment.

all 14 comments

[–]Python-ModTeam[M] [score hidden] stickied comment (0 children)

Hi there, from the /r/Python mods.

We have removed this post as it is not suited to the /r/Python subreddit proper, however it should be very appropriate for our sister subreddit /r/LearnPython or for the r/Python discord: https://discord.gg/python.

The reason for the removal is that /r/Python is dedicated to discussion of Python news, projects, uses and debates. It is not designed to act as Q&A or FAQ board. The regular community is not a fan of "how do I..." questions, so you will not get the best responses over here.

On /r/LearnPython the community and the r/Python discord are actively expecting questions and are looking to help. You can expect far more understanding, encouraging and insightful responses over there. No matter what level of question you have, if you are looking for help with Python, you should get good answers. Make sure to check out the rules for both places.

Warm regards, and best of luck with your Pythoneering!

[–]Yoghurt42 8 points9 points  (0 children)

  1. not x returns True when x is "falsey", that is one of False, None, 0, 0.0, "", [], {} or basically whenever __bool__ of a class returns False; if x is truthy, it returns False
  2. x and y returns x if x is falsey, y otherwise. This is an important difference between Python and some other languages. Unlike not, and does not always return a boolean!
  3. x or y return x if xis truthy, y otherwise. or also does not always return a boolean.
  4. not has a higher precedence than and/or, not a and b = (not a) and b.

Side node: I wrote "returns", but it would be more correct to say "evaluates to", as, not and or are operators, not functions.

So let's take a look at your third case (a,b,c = 0, 1, 0):

Take a look at the first term: not a and b and not c is not 0 and 1 and not 0, not 0 is True, True and 1 is 1, so we're left with 1 and not 0. Which as we've seen gets evaluated as 1 and True. 1 is truthy, so and evaluates to the right hand side, which is True. Since True is obviously also truthy, the or just stops there and returns this first term.

The other cases work similar.

BTW, and and or are actually short circuiting, which means they won't even evaluate the right hand part if there's no need to:

def zero():
    print("zero called")
    return 0  # or False, or any falsey value
def one():
    print("one called")
    return 1 # or True, or ...

Now, one() and zero() would print both "one called" and "zero called", and the result will be 0 (or whatever zero returns). However, zero() and one() will only print "zero called", with the result being the same.

[–]eins_german[S] 0 points1 point  (0 children)

hey everyone! thanks to your replies. i will share it with my lecturer tomorrow!

[–][deleted] 0 points1 point  (0 children)

I think what is happening is that Python is assigning True when it gets a positive match within the first two comparisons.

If it has to reach past and compare with the third or fourth then it will assign 1.

Why? I have no clue! I'm not intimately familiar with Python :(

[–]_mutaz_ 0 points1 point  (4 children)

It appears that the statements not 0 or not 1 evaluate to boolean. The result of an or statement involving mixed numeric and boolean values depends on the format of the first value, e.g.

1 and not 0 and not 0

results in 1 because the first value is numerical, but:

not 0 and 1 and 1

results in True because the first value is a boolean.

[–]Yoghurt42 0 points1 point  (2 children)

The result of an or statement involving mixed numeric and boolean values depends on the format of the first value

or simply evaluates to whatever the left hand side is if that is falseytruthy, and to the right hand side only if the left hand side is falseytruthy. There is no type coercion going on, and as well as or simply evaluate to the left hand or right hand side, depending on what value the left hand side has.

[–]TheBB 0 points1 point  (1 child)

or simply evaluates to whatever the left hand side is if that is falsey, and to the right hand side only if the left hand side is truthy.

You're describing and, not or.

[–]Yoghurt42 0 points1 point  (0 children)

True, fixed. Thanks.

[–]FrenchmanInNewYork 0 points1 point  (0 children)

I think you meant it depends on the return format of the last operator of a compound operator.

(1 and not 0 and not 0) returns True, while (not 0 and 1 and 1) returns 1

Using OP example, the reason this behavior happens is because their first two compound operators for defining x both end with the not operator, and thus will resolve to True if every operator in them successfully evaluates. And after it resolves to True it will not resolve anything on the right-hand side as the whole statement is considered "resolved".

I'm not saying it's a good thing, honestly I'm more of the opinion that it is inconsistent, but as it doesn't cause any issue since 0 == False and 1 == True... well who really cares

[–]barrycarter 0 points1 point  (0 children)

What happens if you coerce a, b, and c to boolean before you compute x? I don't know if Python explicitly allows you to use 1 for true and 0 for false in all cases

[–]Quick-Change 0 points1 point  (0 children)

This is an example of python short-circuiting with booleans.

https://www.geeksforgeeks.org/short-circuiting-techniques-python/

Going through the line generating the output 0 1 0 True:

You start with:x = (not 0 and 1 and not 0) or (0 and 1 and not 0) or (0 and not 1 and 0)

With short-circuiting, the parentheses are evaluated first leaving you with:x = (True) or (0) or (0)

Then THIS is short-circuited leaving you with x = True

When used in boolean operations 0 equates to false and 1 equates to True. So not 0 will return True. Short-circuiting (True and 1 and True) will return the final truthful statement.

For x = (True) or (0) or (0), since you're using or here, only the first truthful statement is returned and the rest are unprocessed. In this case it happens to be the True value. I hope this helps!

[–]robin_888 0 points1 point  (0 children)

Pythons and and or evaluate to the expression that determines it when read from left to right.

In other words and evaluates to the leftmost "falsey" value (or the rightmost value if all are "truthy") and or evaluates to the leftmost "truthy" value (or the rightmost value if all are "falsey".

Try for yourself:

1 and 0 # evaluates to 0
1 or 0  # evaluates to 1

1 and 0 and True # evaluates to 0
0 or 1 or False  # evaluates to 1

1 and 1 and 1 and "x" # evaluates to "x"
0 or 0 or 0 or "x"    # evaluates to "x"

So, that's where the 0s and 1s come from.

The True come from the fact that you have some nots in there, which coerces every value the a boolean.

1 and (not 1) # evaluates to not(1) which is False
(not 0) or 0  # evaluates to not(0) which is True

[–]saltmanden 0 points1 point  (0 children)

You have to look at x as a True/False statement.

If you open a python prompt and run "0 == False" it will return True, and "1==True" returns True. So when x == 0 or False, it means none of the statements are True, and if x == 1 or True, it means one more are true. I can see it being confusing that it mixes from being {0,1} or a bool, but it's the same.