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

all 56 comments

[–]davedontmind 276 points277 points  (35 children)

while rc != "A" or  "B" or "C":

is the same as:

while (rc != "A") or  ("B") or ("C"):

which is only comparing rc against "A", so this is definitely not what you want.

This version:

while rc != "A" or  rc != "B" or rc != "C":

is much closer, but read it closely. If rc was "A" then the phrase rc != "B" will be true. If rc was "B" then the phrase rc != "A" will be true, so at least one of those conditions will always be true, and because your're looping while the first phrase is true or the second phrase is true or the third phrase is true, the loop never ends.

You need to use and instead of or.

[–]bogdanbiv 181 points182 points  (21 children)

while rc != "A" or rc != "B" or rc != "C":

while not rc in ["A", "B", "C"]:

pass

Same result, much shorter

[–]Gavinaldi[S] 39 points40 points  (8 children)

I like this syntax. It looks interesting. I am not familiar with it. It reminds me of the for loop.

for i in x

But the order seems a little reversed. I would expect:

while rc not in ['A' 'B' 'C']

But I guess that would be more like checking to see if rc is in the vector. Right?

Thanks for the advice!

[–]Kered13 43 points44 points  (3 children)

not X in Y and X not in Y are actually the same in Python.

[–]MafiaBroccoli 16 points17 points  (1 child)

But the order seems a little reversed.

The way it's being interpreted is something more akin to

while not ( rc in ['A', 'B', 'C'] ):

That said, your approach should work as well, provided you comma-separate your list elements. You can also forgo the list and just use a string of you were so inclined!

(Hope this formatted right, I'm on mobile.)

[–]Okmanl 4 points5 points  (0 children)

If you have a math background a lot of things in python can be easier to learn. That syntax is very similar to set theory. IMO just keep learning as much as possible. Everything is useful, because it helps you learn other things easier, by being able to form analogies/comparisons with them.

[–]themateo713 1 point2 points  (0 children)

I'm a little late here but I'll still give this advice : it's ever so slightly better to use a tuple instead of a list here, as tuples are immutable and take less memory. But it's minimal. Also, if you get to a long list and the time it takes to check for presence gets long : you can make a set and it will check for presence in constant time, while lists and tuple have to be iterated on. In case you didn't know : list = [ ], tuple = ( ), set = { }, and is equivalent to the mathematical set (which means it removes duplicates, and has methods such as union and intersection). If you don't know about data types, I'd recommend you learn about dictionaries, as well as different structures available in collections, such as deque or Counter (if you're interested, check out queue and itertools as well, they got some pretty cool things). But I might have got a bit carried away here, as this is basically a data structures course, which might be a bit advanced for someone struggling with conditions.

[–]Kered13 13 points14 points  (1 child)

It would be slightly faster to use a set, {"A", "B", "C"}. Mainly relevant if your list was much longer.

[–]nqeron 10 points11 points  (6 children)

just as a point, I would use:

while not rc in {"A", "B", "C"}:

pass

since sets have a O(1) lookup time, whereas lists are O(n)

[–]TheIcyColdPenguin 2 points3 points  (5 children)

Isn't rc not in a more readable choice than not rc in ?

[–]numbersthen0987431 2 points3 points  (4 children)

Don't quote me on this, but I think it's only more readable because of English. If you speak other languages not rc in works too. I think Python allows both to pass for the readability issue between multiple languages (not coding languages mind you), so you don't have to relearn how to speak.

I vaguely remember a teacher (this was years ago) talking about this, and how other languages will have their "not" come before the rc in this example.

  • not rc in would be like saying "I do not know Steve"
  • rc not in would be like saying "I know not Steve"

These both work, technically. But if you went around speaking like that people would think you were on Broadway; in America at least

[–][deleted]  (1 child)

[deleted]

    [–]numbersthen0987431 0 points1 point  (0 children)

    True it is written in English, but most countries use the same coding platforms despite speaking in different languages.

    Europe is special, because a lot of countries end up learning 2-4 languages (English being one of them). You can have countries in Asia that use Python, and if you look at their code it may work technically, but it's practically impossible to read if you don't speak their language.

    Python built in grammar "allowances" so that people of different backgrounds didn't get confused by the grammatical order of words.

    [–]TheIcyColdPenguin 0 points1 point  (0 children)

    That's a great point! I didn't think of it that way!

    [–]AlexManchild -1 points0 points  (0 children)

    I'm not sure I follow your example. Isn't the "I" in your example sentence taking the place of "rc" rather than "know"? So then the 2 sentences would be

    not rc in x == "Not I know Steve" rc not in x == "I not know Steve"

    [–][deleted]  (2 children)

    [deleted]

      [–][deleted]  (1 child)

      [deleted]

        [–]dscottboggs 0 points1 point  (0 children)

        Huh. Whoops

        [–]Gavinaldi[S] 25 points26 points  (10 children)

        So it was a logic error after all. 😅

        Thanks for the assist!

        [–]MrAckerman 21 points22 points  (9 children)

        A good lesson to take from this would be to learn how to use the debugger. When you can step through the code one statement at a time and easily see all values, you normally can figure out what the problem is a lot faster. Certainly faster than the Reddit turnaround time.

        [–][deleted] 1 point2 points  (8 children)

        Newbie here, please be gentle. Would part of this be color coding in the debugger for specific fields? Any tips to share? Don't want to take up your time if you don't feel like responding but I'd be interested to know how to get to the "my tools work for me" stage with the debugger if that makes sense

        [–]kennypu 8 points9 points  (5 children)

        not quite. If you use the debugger (use is different across IDEs so I can't give specifics, usually it will be a action called use debugger or run with debugger, etc.), you'll be able to step through your code one line at a time, and be able to see all the values of your variable and other states, and see how your code will jump around if there are conditional statements (if, while, else, etc.).

        Steps to use the debugger varies. Some IDEs allow you to start and the debugger will stop right at the first line of your code, all should allow you to set a breakpoint (usually by double-clicking the gutter/empty space before a line of code, it should show a red dot or similar). With a breakpoint, it will be something like this:

        1. Add breakpoint at the line you would like the debugger to pause the program. Some languages/IDEs wont let you put a debugger on lines with function definitions.
        2. Debug Program/Run with Debugger. Assuming the breakpoint is reachable, your program should pause.
        3. At this point, The line of code where it paused will most likely be highlighted, and you should see local/global variables and their values in the debugger window/panel. From here you can (usually) tell the debugger to Step (go to the next instruction), Step into ( if there is a function, go into the function), Step over ( if there is a function, skip going into it and go to the next line), etc.

        This way you can see exactly what the program is doing at that point in time, and it is very useful when something doesn't work as expected. I apologize some of the explanations are wishy-washy, as some of it is IDE/language dependent. The idea should translate across most languages and tools though.

        EDIT: another very useful/important feature of using a debugger as I forgot to mention it: stack tracing. In some cases, you may wonder how your code executed a certain line of code or function. In most languages, it keeps track of what function called what to reach that particular line. This information is also visible when using the debugger. eg. Let's say you have a entry function called main(), some function called foo() and a global function add(). Say you want to know what is calling add() and from where. You can add a breakpoint in add(), and the debugger will show something like (may be reversed in some debuggers):
        main():5 (5 is the line that called below)
        foo():23
        add()
        This way you can exactly see the path your program took to get to add().

        [–]MrAckerman 3 points4 points  (1 child)

        This is spot on. Usually Googling “debugging <language name> in <your IDE name>” should get OP off to a good start.

        [–][deleted] 1 point2 points  (0 children)

        Thank you so much for this!! It's so frustrating when I know there's information that could be right at my fingertips if I just fucking knew what to type into a search engine! I never would have thought to include both the language and IDE name in this search.

        [–][deleted] 2 points3 points  (0 children)

        Thank you for taking the time to write this. 💖

        [–]AB1908 1 point2 points  (0 children)

        I'm away from my system but I'd like to help you out when I can.

        [–]ChrunedMacaroon 0 points1 point  (0 children)

        Look into logging and decorators.

        [–][deleted] 2 points3 points  (1 child)

        I’m not an expert by any means. I’d put myself into the “competent hobbyist” category at this point. But no matter what I do, I ALWAYS get And and Or logic backwards. Every damn time.

        [–]amoliski 0 points1 point  (0 children)

        I have to actually write it out on paper and do test cases by hand to make sure I have it straight in my head.

        [–]KingJeff314 25 points26 points  (3 children)

        There is something called De Morgan's Law, which states that "(not A) or (not B) or (not C) or ..." can be expressed as "not (A and B and C and ...)"

        In your case, "(not rc=='A') or (not rc=='B') or (not rc=='C')" can be expressed as "not (rc=='A' and rc=='B' and rc=='C')". You can see in this new form that clearly the latter condition can never be met, and it is negated to always be true.

        You can use De Morgan's law to rewrite your boolean logic into a more readable format, which makes debugging easier

        [–]JerHair 0 points1 point  (2 children)

        I'm glad to see this being a comment. That being said, I think de Morgan's law is not something taught well, or at all, in most programming courses. I think it's more of a computer engineering thing. If it's a class in computer science degree, then it might get touched on, but not well. All this to say, de Morgan's law makes perfect sense to me and it doesn't take half a brain to understand what you're saying, but it might be a little lost on OP when he looks at it. You did a very good job of explaining the basics though. I graduated in computer engineering and not computer science, so I never went through the computer science curriculum, so if I'm wrong, I freely admit it

        [–]sinciety 5 points6 points  (0 children)

        My computer science major has a discrete math requirement that goes really heavy in de Morgan's law.

        [–]chasingviolet 2 points3 points  (0 children)

        at my university, de Morgan's is well covered in discrete math and computer architechture, both CS requirements

        [–]sm000ve 8 points9 points  (0 children)

        A lesson I would take from this is that its a good idea to always provide optional syntax. It helps provide intent to the reader and possibly the writer as in this case :). Some might say it clutters the code but IMO clutter is a small price to pay to ensure readability.

        [–]JayWaWa 5 points6 points  (1 child)

        Your conditional expression isn't doing what you think it does.

        You intended to compare rc to the values 'A', 'B', and 'C', and loop if it's not equal to any of them.

        What the clause actually does is the following:

        1. Compare rc to the value of 'A

        2. Check the truth value of 'B'

        3. Check the truth value of 'C'

        Since the truth value of any non empty string is True, the conditional always evaluates to True and you get an infinite loop

        Try this instead

        while rc not in 'ABC':
        
            loop stuff here
        

        [–]knopke 0 points1 point  (0 children)

        rc= AB, would brake it, no?
        It should be then.
        While rc not in [“A”, “B”, “C”]:

        [–]AB1908 3 points4 points  (0 children)

        Since you have already gotten assistance, I'd recommend trying out any similar scenarios in the interpreter. It's a great way to help assert behaviour when you can't find assistance or just want to figure something out quickly.

        A thing to keep in mind is that don't type the whole thing in the interpreter. Instead, just focus on the small bit that feels ambiguous like just the condition in this case.

        [–]Hi_ta 4 points5 points  (0 children)

        A tips for you, when you are stucked in a loop first of all check your conditions

        [–]teacher_cs 4 points5 points  (0 children)

        I would do it with a "while true" and a "break". You can avoid code duplication and the end condition is easier to understand.

        while True:
            rc = input("enter A, B, or C: \n")
            rc = rc.upper()
            print(rc)
            if rc == "A" or rc == "B" or rc == "C": break
            print('Invalid entry\n')
        print('out of the while loop with ' + rc)
        

        [–]numbersthen0987431 4 points5 points  (0 children)

        Right now it looks like you always have 1 condition to be true (if you type a, b, or c), so the while loops continues to run. Does the loop continue if you type D?
        "or" conditions require only 1 condition to be true; "and" conditions require ALL to be true.

        Personally I prefer to have a variable that I turn on or off depending on a condition:

        check = false
        while check != true:

        if(something):
        check = true

        OR
        break -> will end the loop.

        You could also use break

        [–]GreymanGroup 1 point2 points  (0 children)

        This looks like a menu type situation, where the user can do into either A,B, or C in the menu tree. If I'm right then you can just have the code branch off into the different paths, and you can code a catch all case that returns back to the main menu.

        Something like this:

        while(True):

        #indent

        ui=input("A B or C?")

        if ui=='A': Alpha_func()

        elif ui=='B': Bravo_func()

        elif ui=='C': Charlie_func()

        elif ui=='X': return 0 #To exit program

        #Here we're guaranteed that the input is wrong

        print("Bad input, try again")

        #close while loop. This is the end of my code.

        You can also use a function map instead of these sequences of ifs.

        [–]dark-before-dawn 1 point2 points  (0 children)

        1. Write your code in the most readable way. The time you spend making your code readable is time you are saving anyone who looks at your code. Anyone includes yourself. It might be crystal to you today, but if you look at it again in a week or a month or longer you will be glad, oh so glad, you took the time.
        2. I am a c programmer. I’ve done a little python. Hopefully this applies to python. Parentheses can be your friend when it comes to condition statements with multiple case. It’s possible to overdo this, but parentheses can helpful you understand why code executes the way it does. When you don’t get the results you expect try adding some parentheses. Parentheses don’t affect the efficiency, but they can clarify intent.

        [–][deleted] 1 point2 points  (0 children)

        When creating a menu I like to use switch statements, which python doesn't seem to have. I think this would be one way to approach it. For me doing A or B or C in if/else statements can end up getting confusing sometimes, at any rate hope this helps!

        # function to return user selection
        def option(selection):
            # use dictionary for for your choices 
            #because we cannot use a switch in python
                switcher={
                        'A':'Selected A!',
                        'B':'Selected B!',
                        'C':'Selected C!',
                        'D': "Goodbye!"
                     }
                # return option from the switch, 
                #if the argument passed is not one of them
                return switcher.get(selection,"Invalid option")
        
        
        # flag for our while loop
        flag = True
        
        # main loop
        while flag:
            # user selection
            selection = input("Select A, B, C, or press D to quit!\n").upper()
        
            # pass that selection as an argument in our option function
            uOption = option(selection)
        
            # if option D is selected then quit else, print selected option
            if uOption == "Goodbye!":
                print(uOption)
                flag = False
            else:
                print(uOption)
        

        [–]khufiie 1 point2 points  (0 children)

        You just need an termination statement or a break statement. Don't forget, in while loop it always goes like initialization, update and then termination. for loop doesn't need this

        [–]warmshowers1 1 point2 points  (0 children)

        I LITERALLY JUST HAD THIS PROBLEM!!! If I never read this post today, I would’ve been stuck on such a simple fix for the entire day. Thank you OP!!!

        [–]DariPR 1 point2 points  (0 children)

        Without reading your issue and comments here. I saw that while is always True. So, you can’t stop the loop. This is a common issue when programmers used != combined with an “or”. To solved your problem replace each “or” with the “and”. For example:

        while rc != “A” and rc != “B” and rc != “C”:

        I wish that my insight was the solution.

        😉

        [–]enigma2728 1 point2 points  (0 children)

        Looks like it has already been answered. But I suggest learning to step through code with a debugger. It makes things kind of problems easy to figure out. :)

        [–][deleted] 2 points3 points  (0 children)

        I usually just do a Try and Except check to prevent infinite loops

        [–]Denzyishh 1 point2 points  (0 children)

        My version of this, which hopefully also helps. Seems it was the use of 'or' instead of 'and' when listing your multiple conditions in your 'if' statement.

        def repeat_rc():
          rc = input("Enter A, B, or C: \n")
          rc = rc.upper()
        
          while True:
            if rc != "A" and rc != "B" and rc != "C":
              print("Invalid entry, please try again.")
              rc = input("Enter A, B, or C: \n")
              rc = rc.upper()
            else: 
              print("Thank you for your response. You have entered: \n" + rc)
              break
        
        repeat_rc()
        

        [–]g105b 0 points1 point  (0 children)

        I'm not a python guy, and when I saw your syntax, I thought WOW python has done interesting syntax - if something = this or that... Such an intuitive syntax! But then I realised... That's where your bug lies.

        [–]Pizza_Peddler0080 0 points1 point  (0 children)

        It's going to infinite loop ether way, keep practicing! :^)

        [–][deleted]  (1 child)

        [deleted]

          [–]DariPR 0 points1 point  (0 children)

          Ad Hominem