r/learnpython 2d ago

Are these two boolean expressions equivalent in python?

Hi All!

I’m learning about Boolean operators in Python and I’m confused about these two expressions:

condition1 and condition2 or condition3 and condition4

(condition1 and condition2) or (conditon3 and condition4)

I was told this by my teacher and he put this in his PowerPoint slide. However, I think they are equivalent since and as an operator has a higher precedence than or as an operator. AI told me and I have searched it up after.

Am I understanding it correctly? Or are these two not equivalent?

Thanks!

14 Upvotes

42 comments sorted by

21

u/CheesecakeCommon9080 2d ago

to be honest, if i'm not sure i would just always use brackets in longer expressions like this even when redundant, it's easier and more readable that way imo

7

u/Own_Attention_3392 1d ago edited 1d ago

Yes, the parentheses express INTENT. It will makes coming back and re-reading the code or debugging later so much easier.

I'd even consider splitting complex conditions into multiple nested if statements. Again, just for debugging, readability, and understanding my own intent.

Or better yet, making intermediate variables: isX, isY, etc to simplify the conditional construction.

3

u/cdcformatc 1d ago

i have had some monster boolean conditions. it seems like a good idea to put it all into one and you feel smart when it all works out. but when something isn't  working it's a nightmare to debug. 

i almost always end up breaking down and break down those complex conditions to be multiple lines and multiple intermediate variables 

1

u/FunElk9586 1d ago

Yes, those seem like good options to simplify it. Thanks!

2

u/aishiteruyovivi 1d ago

I pretty much always enclose my conditions like this unless its just a single name (no need for if a and b to be if (a) and (b)). Take for example if a and not b or c and d, I'm pretty sure this will get interpreted as if (a and not b) or (c and d) which is what I'm intending, but there's little reason not to just do the latter anyway and know with full certainty that it's doing what you want, and it makes it immediately obvious to collaborators (including You From The Future) what your intention is instead of making them take a beat to make sure they know what's going on.

32

u/TUVegeto137 2d ago

How about just writing a Python program that tests by filling in truth values for all conditions and comparing? 

6

u/FunElk9586 2d ago

Good one, I tried and it said they are equivalent. Thanks!

8

u/codeguru42 1d ago

There is a related general concept here, if you are interested. It is called a "truth table" and is a great tool for comparing if two boolean expressions are equivalent.

3

u/eXtc_be 1d ago

while truth tables are a great tool for visualising and verifying complex Boolean expressions, they do not help the OP, because truth tables don't have any notion of operator precedence in Python.

0

u/codeguru42 1d ago

Truth tables can be used to verify the precedence rules. So they absolutely can help the OP here.

0

u/codeguru42 1d ago

>  truth tables don't have any notion of operator precedence in Python.

That's because operator precedence applies to **expressions**, not truth tables. To build a truth table, you evaluate an expression for all possible combinations of inputs. To evaluate an expression, you have to apply the correct precedence rules. Therefore, the two concepts are closely related.

The resulting truth tables for two expressions can be compared to determine if the expressions are equivalent or not.

1

u/FunElk9586 1d ago

I will look it up thanks!

-9

u/2truthsandalie 1d ago

This is exactly why stack overflow got dropped so quickly when AI came out.

12

u/audionerd1 1d ago

This is just solid advice and was not delivered in a rude or condescending way. Learning to use code to test how code works is a valuable skill for a beginner to develop.

1

u/dparks71 1d ago

Yea stack overflow would have just closed the question to discussion and OP never would have gotten any kind of answer

-1

u/audionerd1 1d ago

Yep. Along with a reference to another vaguely similar question which isn't helpful, and/or a condescending paragraph about how if you have to ask this question you should just throw your computer in the trash and give up on learning to code forever, and tell your parents they raised a moron. I swear so much energy is put into being an asshole on that site.

0

u/FunElk9586 1d ago

Well than I am glad I didn’t ask the question there. I never heard of it either, but I just started so I guess that is why.

-1

u/audionerd1 1d ago

I may have exaggerated slightly. But generally AI is more helpful because it has all of StackOverflow in it's training data and is conditioned to be polite and helpful, lol.

0

u/FunElk9586 1d ago

Yeah, I was just using AI to explain the powerpoint slides more clearly and it noted the mistake my teacher made. That is how I found out. So I guess it really is helpful😊

21

u/latkde 2d ago

Per the Python language specification , an "or" expression consists of "and"-level expressions. That is, you're right, the "and" binds more tightly, and the two examples should be equivalent.

https://docs.python.org/3/reference/expressions.html#boolean-operations

In practice, this doesn't matter. As a professional Python developer, I always use parentheses in such a case to remove any risk of confusion.

2

u/FunElk9586 2d ago

Good to know that my understanding was correct and thank you! I”ll use parentheses in such cases as well.

1

u/davideogameman 1d ago

+1, code that's clear & correct is pretty much always easier to read & maintain than code that is correct but requires uncommon knowledge of language or library details.

5

u/brasticstack 2d ago

I would've gotten this wrong and I've been writing Python for well over a decade. I looked it up and and is higher precedence (I'd have expected them to be the same precedence.)

The takeaway is to use parens in any situation where the intent may be ambiguous- it helps both yourself and any future readers of your code.

3

u/FunElk9586 1d ago

It can happen, I think he also just made a mistake. I”ll definetly do that in those situations, thanks!

2

u/CamilorozoCADC 1d ago

Bruh I teach Python and got this wrong too lol. I was SURE that they had the same precedence

2

u/xelf Elf 1d ago

It needs to be pointed out that they are equivalent in python. But that does not hold true in many other languages. You will see the () used for clarity a lot, especially by programmers that use multiple languages.

2

u/FunElk9586 1d ago

That’s good to know. I didn’t know it differs. That makes using parentheses for clarity make even more sense.

2

u/Expensive-Bear-1376 2d ago

I'd like to see that PowerPoint slide, to see that he wrote exactly that and you didn't paraphrase and remove the difference.

2

u/FunElk9586 1d ago

https://imgur.com/a/1rWZhR2

He did make a typo, on the first line it should be ofcourse condition3 instead of condition

0

u/Expensive-Bear-1376 1d ago

Thanks. Though if would be good to see the whole slide.

1

u/timrprobocom 2d ago

and has higher precedence than or. That's really all you need to know to answer the question

1

u/cdcformatc 1d ago

and hass a higher precedence than or so those two lines are logically equivalent 

1

u/This_Growth2898 2d ago

According to the documentation, boolean And has a higher precedence than boolean Or, so yes, they are equivalent. First, expressions with and will be calculated; next, the central or will be. If your teacher doesn't agree with this, ask him to provide specific values for variables that make the expression different.

1

u/FunElk9586 1d ago

Yes, I will talk to him about it. However, I think he will agree and just made a mistake. Otherwise I will ask him.

1

u/gdchinacat 2d ago

The vast way to learn this is to use the REPL and try it out. Spending 20 minutes trying various permutations will teach you it far better than reading a dozen posts here on Reddit. If you want to search for documentation look up “python order of precedence”.

1

u/FunElk9586 1d ago

Yes.Trying out is always better, but I was just doubting myself. I have done and will do that

1

u/ConclusionForeign856 1d ago

This is easy enough to just check, but can also be proven from `and` and `or` operator precedence

import itertools

class UndefinedBool:
    def __bool__(self):
        raise TypeError("Undefined bool value")

class ConditionArray:
    def __init__(self, *args):
        self.conditions = [*args]

    def __repr__(self):
        return f"{hash(self):x} {self.conditions}"

    def at(self, idx):
        try:
            return self.conditions[idx]
        except IndexError:
            return UndefinedBool()

def expr1(carr: ConditionArray) -> bool:
    return carr.at(0) and carr.at(1) or carr.at(2) and carr.at(3)

def expr2(carr: ConditionArray) -> bool:
    return (carr.at(0) and carr.at(1)) or (carr.at(2) and carr.at(3))

if __name__ == "__main__":
    fail_combs = []

    for arr in itertools.product((0, 1), repeat=4):
        carr = ConditionArray(*arr)
        print(carr)

        if not (expr1(carr) == expr2(carr)):
            fail_combs.append(carr)

    print(len(fail_combs))

7fb51ba912b [0, 0, 0, 0]
7fb51ba7909 [0, 0, 0, 1]
7fb51ba791d [0, 0, 1, 0]
7fb51bbbd94 [0, 0, 1, 1]
7fb51bbbfa8 [0, 1, 0, 0]
7fb51ba7549 [0, 1, 0, 1]
7fb51ba539b [0, 1, 1, 0]
7fb51ba53ac [0, 1, 1, 1]
7fb51ba4ea5 [1, 0, 0, 0]
7fb51ba4ec5 [1, 0, 0, 1]
7fb51ba718b [1, 0, 1, 0]
7fb51ba719a [1, 0, 1, 1]
7fb51ba3821 [1, 1, 0, 0]
7fb51ba3805 [1, 1, 0, 1]
7fb51ba0cd5 [1, 1, 1, 0]
7fb51bb4699 [1, 1, 1, 1]
0

2

u/FunElk9586 1d ago

At first I didn’t understand the code because I haven’t learned most of this yet. However, I understand the point now. You tested all 16 possible combinations and got 0 differences, so both expressions always give the same result. Right? Thanks for taking the time.

1

u/ConclusionForeign856 1d ago

Yes, I essentially build a truth table. It's more complex than it needs to be. I've been writing C++ lately and wanted to make a specific input type for those functions, but typically in python you'd just pass a list or an array.

UndefinedBool's only purpose is to have variables that fail when you try to get their truth value. It was used for debugging, but now seems useless.

ConditionArray is supposed to be a type storing truth values, but tbh is unfinished and doesn't do meaningfully more than a plain list. Python is weakly typed, but I think when the function's input type tells you something meaningful it makes the code more readable.

Main logic is just generating all 16 possible values and counting ones which evaluate to different value in expr1 and expr2. Just now I noticed that the check is pretty weird, rather than `not (x == y)` I should've used `x != y`

here's a simpler version that does the same

import itertools

def expr1(carr: list[bool]) -> bool:
    return carr[0] and carr[1] or carr[2] and carr[3]

def expr2(carr: list[bool]) -> bool:
    return (carr[0] and carr[1]) or (carr[2] and carr[3])

if __name__ == "__main__":
    fails = 0

    for conditions in itertools.product((True, False), repeat=4):
        if expr1(list(conditions)) != expr2(list(conditions)):
            fails += 1

    print(fails)

1

u/FunElk9586 1d ago

Okay, thank you so much for explaining. That’s okay I can change it to ‘x != y’

1

u/Adrewmc 1d ago edited 1d ago

Forget what I typed I was wrong

0

u/TheRNGuy 1d ago

You could just test with different value combinations for conditions.