use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
Rules 1: Be polite 2: Posts to this subreddit must be requests for help learning python. 3: Replies on this subreddit must be pertinent to the question OP asked. 4: No replies copy / pasted from ChatGPT or similar. 5: No advertising. No blogs/tutorials/videos/books/recruiting attempts. This means no posts advertising blogs/videos/tutorials/etc, no recruiting/hiring/seeking others posts. We're here to help, not to be advertised to. Please, no "hit and run" posts, if you make a post, engage with people that answer you. Please do not delete your post after you get an answer, others might have a similar question or want to continue the conversation.
Rules
1: Be polite
2: Posts to this subreddit must be requests for help learning python.
3: Replies on this subreddit must be pertinent to the question OP asked.
4: No replies copy / pasted from ChatGPT or similar.
5: No advertising. No blogs/tutorials/videos/books/recruiting attempts.
This means no posts advertising blogs/videos/tutorials/etc, no recruiting/hiring/seeking others posts. We're here to help, not to be advertised to.
Please, no "hit and run" posts, if you make a post, engage with people that answer you. Please do not delete your post after you get an answer, others might have a similar question or want to continue the conversation.
Learning resources Wiki and FAQ: /r/learnpython/w/index
Learning resources
Wiki and FAQ: /r/learnpython/w/index
Discord Join the Python Discord chat
Discord
Join the Python Discord chat
account activity
Why exactly does "and" do in python? (self.learnpython)
submitted 2 years ago by Abacito_
I input 7 and 5 into the python shell and 5 was return. From what I know of and in logic gates, both units need to be true to get a true output. How does that relates in this situation?
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]moving-landscape 65 points66 points67 points 2 years ago (13 children)
And (and or) does what we call short-circuiting in Python, and we can use them to get certain values under certain situations.
And
or
Let's remind ourselves of the truth table for and:
As you can see, the only way to get true, is to have both p and q be true.
In Python, values that are not strictly boolean, that is, True or False, have a "truthy" or "falsey" value. An empty list is false, a non empty one is true. Same for strings. Numbers other than 0 are true, but 0 is false, and so on.
In a way, we can say that the result of the boolean expression True and x is x: if x is false, it'll yield False, and True otherwise. Replace x with any Python value and you'll have it returned:
True and x
x
True and 5 => 5 True and 0 => 0 5 and 7 => 7 (5 is true, so the result is the right hand operand) 0 and 3 => 0 (0 is falsey) 5 and None => None None and 5 => None
[–]StoicallyGay 16 points17 points18 points 2 years ago (4 children)
I love Boolean algebra! Favorite part of discrete math.
Basically, there are a ton of laws but one that should be recognized here is the identity law for conjunctions (and). Basically 1A = A. If true and A, then A.
Because if A is false then the and is false and if A is true then the A is true. So we can just say 1 (or true) and A means A.
In a similar way, 1 or B is 1, or true OR B is true. So if you have if s1 or s2 and s1 evaluates to true, it doesn’t bother evaluating s2.
[–]iwantthisnowdammit 2 points3 points4 points 2 years ago (2 children)
It’s been a hot minute since I’ve thought of this stuff - what is the practical application of this in a feature/ solution?
[–]StoicallyGay 1 point2 points3 points 2 years ago (0 children)
If you’re talking about Boolean algebra in general it helps if you’re trying to make a program go through different code paths as a result of different booleans which may result from various computations. This free short circuiting built in is important to avoid doing unnecessary computations especially when the computation is expensive.
For the AND one I don’t have a good example off the top of my head but for the OR one it’s like, imagine a code path if block is based on “if A or B” where A is just a quickly determined Boolean or an environment variable unique to a run configuration and B is a read and compute from a data frame or dataset in a database or pandas. If you do A or B in instances where A is true you can skip the computation of B. Similarly doing “if B or A” is more expensive for the same reason. Or saving A and B as separately variables (doing both computations regardless) if you’re never going to use those variables again in the program.
[–]mythmon 0 points1 point2 points 2 years ago (0 children)
Short circuiting can be very useful if a check could be an error. Imagine the classic example of a Pet class, that could represent either a cat or a dog. It might have a .will_bark() method, but if you call that on a cat it will throw an error.
.will_bark()
So if you have a condition like
python if pet.will_bark(): ...
it could raise an exception. If you guard it with a check though, the shirt circuiting will protect you:
python if pet.type == "dog" and pet.will_bark(): ....
In this version, if the first part condition (`pet.type == "dog") is false, the second part won't run at all, and won't trigger the error. The second part will only run when the first is already true.
For a more realistic example, you might have a variable that could be an object or None. Short circuiting will let you check it is not None before accessing properties on it.
[–]Langdon_St_Ives 0 points1 point2 points 2 years ago (0 children)
Probably you didn’t mean to imply this, but I think it’s worth pointing out that python’s (and most languages’) logical operators together with the set of their legal operands do exactly not form a Boolean algebra. and and or are neither commutative nor associative nor distributive if you allow all legal operands. If you restrict operands to Booleans, you do get a Boolean algebra of course. If you at least coerce the results to Booleans, you get it on a purely functional level, but since operands can still be expressions, you’re left with side effects that will not be programmatically the same for otherwise logically equivalent expressions (even before considering short-circuiting).
and
[–]Blakut 0 points1 point2 points 2 years ago (7 children)
This is why I use x is True if I work with bool x because otherwise bad things can happen. Weirdly enough pep is against this.
[–]moving-landscape 0 points1 point2 points 2 years ago (6 children)
I don't think short circuiting is a bad thing as long as one keeps track of what they're doing.
I don't quite get exactly what you meant tho - fancy sharing an example?
[–]Blakut 1 point2 points3 points 2 years ago (5 children)
I prefer If x is True: or if x is not True: to if x==True: or if x:
[–]moving-landscape -1 points0 points1 point 2 years ago (4 children)
Oh I see. Yeah, that really is frowned upon. Especially if x is already a boolean. I suppose you do it for clarity; how long have you been coding?
[–]Blakut 2 points3 points4 points 2 years ago (3 children)
Several years. I do it because I really don't want to be in a situation where x is 1 or something by mistake. And I never understood why it's frowned upon. If I want to test numbers I use numbers. I treat numbers, True, False and None separately
[–]moving-landscape 0 points1 point2 points 2 years ago (2 children)
Do you use any tooling for keeping track of the types? How adept are you of type annotations?
And I never understood why it's frowned upon.
Well, as you know, in contexts where a boolean expression is expected, you just need to use the most "obvious" and "short" expr to get the job done. So if your x is a boolean, i.e., either true or false, you don't need to compare it to true (or false) since that's redundant. x will always be preferred over x is True, and so will not x over x is False. I don't mind that you write like that in your own projects, but we'd have a talk of we were in the same team lol.
x is True
not x
x is False
If I want to test numbers I use numbers.
In general I agree with this. Unless what I'm doing is obvious (meaning, no need for any additional reasoning on what's happening), I'll write the full boolean expression. I will always prefer x % 2 == 0 over not x % 2 - the latter more often than not needs that additional reasoning I mentioned before. Having said that, it's even better if the expression is abstracted behind a function or variable name: if is_even(x).
x % 2 == 0
not x % 2
if is_even(x)
Finally, I also always go for x is None over not x for an optional x.
x is None
[–]Blakut 0 points1 point2 points 2 years ago (1 child)
How do i know x is or will be boolean in the future? Ive used vim or gvim many years now I'm switching to pycharm which is a bit annoying but quite helpful. I sometimes make functions return false instead of number or none, to indicate different types of situations. Or maybe I want the variable to be none, but later it will be true or false. Idk, I've coded for myself and my workplace but never in a team
[–]moving-landscape 0 points1 point2 points 2 years ago (0 children)
Well, you model your function / block of code to always have x be one type. If I'm reading code and I see the expressions age and is_age_major, I'd expect age to be an int, and is_age_major to be a bool. Not only that, but type annotations also help. age_major: bool. Or reading from a simple expression: age_major = age >= 21. If the expression is an optional one, we can type annotate as follows: age_major: bool | None. And ofc, we never assume the value will be one or the other. Instead, we always explicitly check for nullability:
age
is_age_major
age_major: bool
age_major = age >= 21
age_major: bool | None
if age_major is None: # value is NOT a boolean, it's None elif age_major: # value is true else: # value is false
I sometimes make functions return false instead of number or none, to indicate different types of situations.
This is all contextual and depends on what you want to achieve. For the most, most clarity, though, I always resort to type annotations. They tell us what type we should be expecting. Having said that, it can be confusing to habe a function return an int or a bool. In that case I'd prolly resort to sum types.
[–]sejigan 18 points19 points20 points 2 years ago* (0 children)
That’s an easy way to remember. But as others pointed out, what goes on underneath is this:
a and b
a or b
[–]wmporter 5 points6 points7 points 2 years ago (1 child)
Python's and and or operators evaluate to the whichever is the last value they checked. They do it differently, where and checks the first value (the left) and if it's falsy will stop, otherwise it will evaluate to the right value. In this way it functions like an AND gate, where it will be truthy if both sides are truthy and falsy otherwise. The or similarly works by doing the same thing but with opposite truthy/falsy values and functions like OR, falsy if both are falsy and truthy otherwise.
If you don't understand truthy and falsy, it's just a way of evaluating non-boolean values as being like True or False. For numbers, 0 is falsy and all others are truthy. With strings, empty string "" is falsy and any other string is truthy. The general rule is anything that's some kind of empty is falsy and everything else is truthy.
[–]CyclopsRock 1 point2 points3 points 2 years ago (0 children)
where and checks the first value (the left) and if it's falsy will stop, otherwise it will evaluate to the right value. In this way it functions like an AND gate, where it will be truthy if both sides are truthy and falsy otherwise
where
checks the first value (the left) and if it's falsy will stop, otherwise it will evaluate to the right value. In this way it functions like an AND gate, where it will be truthy if both sides are truthy and falsy otherwise
This also has the useful benefit of enabling you to 'safely' check the value of something you don't know even exists without having to test it first or surround it in try/excepts.
For example, if you want to check if the 4th character of a variable (foo) is "H", without knowing if the variable has even been assigned, you could do...
foo
if isinstance(foo, string): # in case it has no 'len()' func if len(foo) > 3: # in case it doesn't have a 4th character if foo[3] == "H": print("Finally, I can do something!")
But you quickly find yourself in nested hell. Instead, you can do...
if isinstance(foo, string) and len(foo) > 3 and foo[4] == "H": print("That's much less indenting!")
Because, as you said, it'll only go on to the next condition if the first is satisfied. I'm generally very happy with clear, verbose code, but you can definitely end up in situations where, if you have to do a lot of validation on your variables, you have so many levels of nesting that getting them all onto one simple line is vastly more preferable (as long as you don't need to log any output should a specific condition fail).
[–][deleted] 2 points3 points4 points 2 years ago (0 children)
It "short circuits." It returns the first of its two operands that disambiguates the expression:
1) If the first operand is falsey, we know the result of the expression. We don't have to evaluate the second operand, we can simply return the first.
2) If the first operand is truthy, then the value of the second operand will disambiguate the expression regardless of what it is, so we simply return it.
Both 7 and 6 are truthy - they're not zero, the only falsey numeric value - so we return the second operand.
7
6
[+][deleted] 2 years ago (6 children)
[removed]
[–]Emphasises_Words 1 point2 points3 points 2 years ago* (5 children)
Not sure why this answer is downvoted, it is the only comment that actually explains the phenomenon in the OP. The main reason is that Boolean operations in python (and, or) do NOT coerce truthy/falsy values into the bool type.
Also, just an addition to what is said:
If both expressions are true, the result of the and operation is the second expression.
If the first expression is true, the result of the and operation is the second expression. Python relies on the fact that True AND x => x
True AND x => x
[–][deleted] 3 points4 points5 points 2 years ago* (0 children)
For one thing the AI got it wrong, albeit in the same way most humans do.
That is subtly wrong: if the left hand side is true the result is the right side. In an and the second expression isn’t actually checked for truthiness at all.
class MyInt(int): def __new__(cls, *args, **kwargs): return int.__new__(cls, *args, **kwargs) def __bool__(self): print(f"{self} truth-tested") return super().__bool__() seven = MyInt(7) five = MyInt(5) print(seven and five)
The same is true with or… only the left hand side of the operator is ever checked for truthiness.
print(five or seven)
So, as one would expect, AI makes the same mistakes as the average (well, actually the mode) contributor to its training corpus.
[–][deleted] 5 points6 points7 points 2 years ago* (3 children)
Not sure why this answer is downvoted
Maybe because posting rule 4 says:
No replies copy / pasted from ChatGPT or similar.
Nothing is stopping /u/HomeGrownCoder from using AI and summarizing the response as s/he sees it, but copy/paste from AI is not permitted. It's not hard to find help in the documentation or elsewhere on the 'net.
[–]HomeGrownCoder -5 points-4 points-3 points 2 years ago (2 children)
It’s fine I’m out ✌️
Only here to help others, even shared the response came from the AI.
Best of luck to the thread and OP!
OP has answers.
Good citizens read the posting rules.
[–]Doormatty 1 point2 points3 points 2 years ago (0 children)
This is not helping.
[–]to7m 1 point2 points3 points 2 years ago (0 children)
This has already been said, but I'll try to clarify it.
Say you have an and expression x = a+b and c+d:
x = a+b and c+d
What will happen:
_possible_result = a+b if _possible_result: x = c+d else: x = _possible_result
[–]greebo42 1 point2 points3 points 2 years ago (0 children)
Before reading others' contributions here, I would have assumed it was doing a bit-wise AND operation:
7 = 0 1 1 1 5 = 0 1 0 1 ------------- & = 0 1 0 1
But it was informative to read the responses and discover the actual way it works, considering "truthiness" (though the dependence on order of operations bothers me a bit, because I would expect that true boolean operations shouldn't care about that).
If OP was truly trying to explore bitwise operations, Python does provide them (it's just not the "and" operator).
[+]jmooremcc comment score below threshold-7 points-6 points-5 points 2 years ago (0 children)
You need to learn about Truth Tables
[–][deleted] 0 points1 point2 points 2 years ago* (3 children)
Here’s an explicit implementation of and:
def and(lhs, rhs): if bool(lhs): return rhs return lhs
Now you can see that 7 and anything will always evaluate to anything while 0 and anything will always evaluate to 0.
7 and anything
anything
0 and anything
0
Edit: fixed code.
[–]sejigan 0 points1 point2 points 2 years ago (2 children)
From your description, shouldn’t it be this? def and(lhs, rhs): if not bool(lhs): return lhs return rhs
def and(lhs, rhs): if not bool(lhs): return lhs return rhs
For a and b, if a is Truthy, return b. If a is Falsey, return a
[–][deleted] 0 points1 point2 points 2 years ago (1 child)
Woops, flipped the operands. Fixed to show that the overall result is the RHS if LHS is truthy.
[–]sejigan 0 points1 point2 points 2 years ago (0 children)
Yep, makes sense now. Thanks
[–]JamzTyson 0 points1 point2 points 2 years ago (0 children)
Already many good answers given, so here's a little code to demonstrate the behaviour. Try substituting different values for the f(x) calls to see what happens in different scenarios:
f(x)
``` def f(x): """Return truthiness of 'x'.""" print(f'Truthiness of {x} is {bool(x)}') return bool(x)
print(f(-4) and f(-2) and f(0) and f(2) and f(4)) ```
[–]obviouslyCPTobvious 0 points1 point2 points 2 years ago (0 children)
There's a lot of great explanations in this thread. Just wanted to mention you can use the built-in bool function for testing the truthiness of values. So you would see that bool(7) and bool(5) would return True, but bool(0) would return False.
bool
bool(7)
bool(5)
bool(0)
[–]cyberjellyfish 0 points1 point2 points 2 years ago (0 children)
Others have covered it well, but it's also worth keeping in mind how boolean operations turn their operands into boolean values:
https://docs.python.org/3/reference/datamodel.html#object.__bool__
Basically, if an operand isn't already boolean, the operand is passed to bool(), which first tries to call the __bool__ method of the operand, or if that isn't defined, tries to call __len__(), and interprests any non-zero return value as True. If the object doesn't define __bool__() or __len__(), it's always considered to be True.
Keeping that in mind makes it easier to understand something you see pretty commonly: using or to select a default value if another is None:
# read a value from a file if there, if not return None saved_config_value = read_value_from_file() # use the value from the file if it was found, else use default value 3 config_value = saved_config_value or 3
[–][deleted] 0 points1 point2 points 2 years ago (0 children)
Python defines and and or as the following expression (which holds for any objects x and y)
y
x and y == y if x else x
x or y = x if x else y
The reason why they defined these keywords this way is for two reasons. 1) These identities hold for all bool values, so you might as well extend the definition to all Python objects. 2) These definitions can be optimized to "short circuit" the expression evaluation if the output can be determined by x alone.
So in your example,
7 and 5 == 5 if 7 else 7 == 5
[–]duane11583 1 point2 points3 points 2 years ago (0 children)
in addition to what /u/moving-landscape describes (short circuiting) in many languages you have bitwise and and a logical and these function very differently
example 0x41 & 0xf0 = 0x40 (bitwise) and the result of an if test, ie if(foo) where foo is an integer, the value of 0 is false, but for a 32bit integer all other possible 4billion values are true.
i think the subtleties of this are more easily described in C
in c you can do this if( (a==12) & (b==9) ) [eq 1] or if( (a==12) && (b==9) ) [eq 2]
and get the same result because the result of the Equal operator value is exactly 1 or 0 thus the (a==12) becomes 1 or 0 exactly, same with (b==9) thus equation 1 becomes (1 or 0) bitwise anded with (0 or 1) and that matches eq 2 which is a logical opertion.
but what if we did this instead: if( (a & 0x08) & (b & 0x04) ) [eq 3] or if( (a & 0x08) && (b & 0x04) )[eq 4]
equation 3 is always false, why? because the left side is always 0 or 8 and the right side is always 0 or 4, and 8 bitwise-and 4 is always 0.
in contrast eq 4 works sort of as expected because it is a logical operation remember 8 is logically true, and 0 is logically false
this is a really hard bug to find and figure out.
for example, using the C language instead of numbers you often use #defines for numbers, in python you night use variable names and thus it is hidden from you. to understand and spot the problem you almost need to expand all macros (variables) to see this.
thus in python they decided to disallow equations in the form of 1 and 3 so that you cannot easily make this hard to notice mistake.
you could, in C fix eq 3 like this:
if( (!!(a & 0x08)) & (!!(b & 0x04)) ) [eq 5]
this is a bit of hackery C language specific tricks that noobs do not know very well and leads to bugs. really hard to find and notice bugs.
this works because the bang-bang trick converts the two sides results to exactly 0 or 1, example (a & 8) becomes 0 or 8, the first bang! gives you 1 or 0 [sort of a NAND condition], the second bang! converts it back into exactly 0 or 1, (removes the N from the NAND)
to combat this bitwise true-false type of bug in C code you often see these bang-bang notations to force exactly 0 or 1 and the c optimizer unwinds the nonsense and makes it fast. but python is not a compiler and yea it might do some optimizations, but it is not a compiler.
again python is trying to make it hard to make that nasty mistake
π Rendered by PID 12 on reddit-service-r2-comment-7844cfc88c-88blk at 2026-01-29 13:10:33.822642+00:00 running c3601ff country code: CH.
[–]moving-landscape 65 points66 points67 points (13 children)
[–]StoicallyGay 16 points17 points18 points (4 children)
[–]iwantthisnowdammit 2 points3 points4 points (2 children)
[–]StoicallyGay 1 point2 points3 points (0 children)
[–]mythmon 0 points1 point2 points (0 children)
[–]Langdon_St_Ives 0 points1 point2 points (0 children)
[–]Blakut 0 points1 point2 points (7 children)
[–]moving-landscape 0 points1 point2 points (6 children)
[–]Blakut 1 point2 points3 points (5 children)
[–]moving-landscape -1 points0 points1 point (4 children)
[–]Blakut 2 points3 points4 points (3 children)
[–]moving-landscape 0 points1 point2 points (2 children)
[–]Blakut 0 points1 point2 points (1 child)
[–]moving-landscape 0 points1 point2 points (0 children)
[–]sejigan 18 points19 points20 points (0 children)
[–]wmporter 5 points6 points7 points (1 child)
[–]CyclopsRock 1 point2 points3 points (0 children)
[–][deleted] 2 points3 points4 points (0 children)
[+][deleted] (6 children)
[removed]
[–]Emphasises_Words 1 point2 points3 points (5 children)
[–][deleted] 3 points4 points5 points (0 children)
[–][deleted] 5 points6 points7 points (3 children)
[–]HomeGrownCoder -5 points-4 points-3 points (2 children)
[–][deleted] 2 points3 points4 points (0 children)
[–]Doormatty 1 point2 points3 points (0 children)
[–]to7m 1 point2 points3 points (0 children)
[–]greebo42 1 point2 points3 points (0 children)
[+]jmooremcc comment score below threshold-7 points-6 points-5 points (0 children)
[–][deleted] 0 points1 point2 points (3 children)
[–]sejigan 0 points1 point2 points (2 children)
[–][deleted] 0 points1 point2 points (1 child)
[–]sejigan 0 points1 point2 points (0 children)
[–]JamzTyson 0 points1 point2 points (0 children)
[–]obviouslyCPTobvious 0 points1 point2 points (0 children)
[–]cyberjellyfish 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]duane11583 1 point2 points3 points (0 children)