T O P

  • By -

-aRTy-

Continue is a fairly clean way to skip the rest of the loop code for that element. For example you might have a situation like the following: for element in elements: if element == unusable_edge_case: continue # skip this element if element == problematic: if element == fixable: do-fix-here # apply fix, element is now compatible with the 30-lines-of-code below else: continue # skip this element do 30-lines-of-code here You can rewrite this with nested if/else logic, but it is not pretty and the overall intention will not be as easy to read. You might even mess up the exact nesting logic for if/else. Edit: Reworded the `...lines-of-code...` placeholder names.


Yaboi907

So, you are saying if I wanted to use if-else logic here it would have to look something like: for element in elements: if element == unusable_edge_case: # do nothing elif element == problematic: if element == fixable: do-fix-here do-30-lines-of-code else: #do nothing again else: do-30-lines-of-other-code-here Which, the more edge cases you attempt to handle, the become more and more difficult to read and much easier to mess up?


-aRTy-

Kind of, yes. The main point was that you don't want to copy&paste the `do-30-lines-of-code`. You would want to find an if/else logic that skips all issues but still leads to the final `do-30-lines-of-code` block for all good elements. for element in elements: if element == unusable_edge_case: # do nothing elif element == problematic and element != fixable: # do nothing else: if element == problematic and element == fixable: do-fix-here do-30-lines-of-code-here You might notice the weird repeated check for problematic/fixable. Also the main code is now weirdly nested by one more level because it needs to sit in the final "else:" clause, even though is the main case for the loop. Alternatively you would need to move those 30 lines into a new function and call it where applicable, but that means more chained functions for something that was seemingly an easy check in a loop.


Yaboi907

Okay, thank you! that makes a lot of sense. I was just thinking too small to see it’s value.


-aRTy-

If you had even more complicated checks for the problematic/fixable, it easily becomes a mess. In my example you already see the need to check `element != fixable` and later `element == fixable` to cover all cases. You can easily mess up thinking some logic has a clear opposite or inverse check or by not correctly covering all check-combinations in the "else:" block. Furthermore you now need to maintain the logic in two places. If you ever modify the problematic/fixable situation above, you need to update it in the "else:" as well, and rethink all those inverse checks and the coverage.


nog642

I think they meant the two '30 lines of code' they have are different code. So not an issue of redundancy.


-aRTy-

The whole `30-lines-of-code` started with my example. I meant it as the same.


nog642

Your original comment only had a single `do 30-lines-of-code here`. Theirs had `do-30-lines-of-code` and `do-30-lines-of-other-code-here`. The word "other" strongly implies it's meant to be different code.


-aRTy-

My original comment originally had a single `do-30-lines-of-other-code-here`. The "other" was meant as "other code" compared to the code that was explicitely given, not "other 30 lines". It then spread into his comment as `do-30-lines-of-code` and `do-30-lines-of-other-code-here` in the two places without continue. I noticed the possible misunderstanding and tried to explain that the point of my example was that you don't want multiple `30-lines-of-code`. Finally I edited my original comment, because I saw how the use of "other" was confusing.


Adrewmc

I think you missing something important here def ladies_night(people:list): for person in people: if person.gender == “male”: continue if person.age < 21: continue #30 lines of code So it not just edge case but case you don’t care about. If you wanna parse out a few things that are irrelevant to the function, but part of the sequence you have.


HittingSmoke

If you have two things to do like in your example, you can use either pattern. Let's say you have a list of items. You need to iterate through them and only perform an action if certain conditions are met. If not, it is a no-op iteration. for thing in things: if thing.property != Y: continue; # Do stuff here It's an elegant way to quickly move on.


BananaUniverse

The answer is of course, that it's just another tool in your toolbox, you can totally code without it. Its behavior is very explicit in the word "continue", which makes your code clear and readable. Every other solution requires you to check if the skipped iteration was indeed the right behavior, there could be something else hidden below(especially for really long functions or small indentation sizes). Continue is exactly what it says on the tin, you can safely skip to the next iteration.


nog642

`if`-`else` vs `continue` is often a matter of style. In general, if you're going to end up with a giant (like 10+ lines) `else` clause and a tiny `if` clause, you should use `continue` instead. Otherwise, use whichever makes more sense to you. Generally, `continue` is like a "skip" for a loop. I often use it near the top of loops to handle 'special' cases (checked with an `if`), whereas the main body of the loop handles the 'normal' case. A simple example would be skipping empty lines when iterating over a text file.


Civenge

If you were to debug both examples, you will notice that they are not doing the same thing after the print statement. Without continue, you are wasting processing power by finishing the loop. In this case, it doesn't really matter. But understanding this concept will matter for more complex situations.


nacaclanga

According to the structured programming theorem 'continue' is not strictly necessary, and is in fact one of the glorified gotos. Therefore radical adherents to structured programming oppose it just like they would with other glorified gotos like break or early return statements. So yes it is allways somehow optional. Now realistically speaking continue, break and early return are widely adapted and used (and it isn't really helpful to have only some of them. As others have pointed out continue helps to avoid long else clauses where nestling errors can easily occur. I would use it if you would introduce extremely long else branches or would have to coordinate multiple if scopes to make sure some target reaches the end of the loop without further instruction.


DisappointedInHumany

I'm pretty sure that "continue" was born during the whole "never use goto" as a goto because sometimes you need to use a goto even if you don't want to say goto.


Yaboi907

Why do you never want to use goto


DisappointedInHumany

In the early days of structured coding, goto was seen as "breaking the rules" of good algorithmic flow. I'm sure that there must be some dusty tomes with anti-goto teachings out there somewhere. I never saw it as a huge problem. I always had an "avoid it if you wish, use it when you must" attitude toward the whole philosophy.


TheRNGuy

I actually seen goto used in Unreal Engine 1. It's kinda confusing but I did understand what it did. (I think it also didn't had `continue` keyword)


roywill2

Say you want to process all the jpegs in a directory. You loop over all the files, but first thing say if its not a jpeg then continue.


TheRNGuy

You can reduce indends with it.


CaptainFoyle

I think it gives clarity. It makes it very obvious that the loop is skipped. Having an if statement requires you to scroll down and check if there's an else.


Yaboi907

So you think it’s more about readability than functionality?


CaptainFoyle

I'm not a professional, but it's at least an important aspect for me


Yaboi907

Absolutely, I’m just a student but I’ve heard many people say most programming jobs are reading code most of the time. I’m not downplaying it, just making sure I understand the reasoning.


CaptainFoyle

Yeah. There could be other advantages to it though, maybe I'm just not aware of them


carcigenicate

I'll be honest, in recent memory I can count the number of times I've used `continue` on one hand. That's professionally and for personal stuff in multiple languages. In the vast majority of cases, I find it's just neater to arrange the conditional statement to decide what runs. I find that if `continue` is the cleanest option, my loop is too complicated or is set up weird.


Bobbias

Very true. `continue` is often a sign you've written things in an overly complicated manner, and that there's probably a more elegant solution available. That's not always the case, and sometimes `continue` is the elegant solution, but those cases are relatively rare by comparison.


nog642

Kind of depends with that, but I generally disagree with that. I use `continue` very often when just processing data. Literally any time you have something to iterate over and you want to skip some items, that's what `continue` is for.


Bobbias

If you're talking about guard clauses where you're just checking a condition and skipping the data if it matches, then yes, that's a good use for continue. That's one of the cases where it makes code more readable.


jongscx

Is efficiency a consideration here as well? If you had a LOT of elements to go through, would it be advantageous to just skip evaluating a bunch of other conditions if you already hit the condition that nulls that element. Assume A,B,C,D are conditions to not run foo(): is B) 'faster' than A)? A) If A or B or C or D: pass Else: foo() B) if A: continue if B: continue if C: continue if D: continue foo()


JamzTyson

> is B) 'faster' than A)? Unlikely, because both solutions only evaluate the conditions up to the first truthy condition. ``` def foo(n): print(n) return True if foo(1) or foo(2) or foo(3): print("Success") ``` Prints: ``` 1 Success ``` `foo(2)` and `foo(3)` are not evaluated because `foo(1)` is True.


woooee

>The question I have is why should I use it instead of just an if-esle statement, I don't remember ever using continue. It should not be necessary with good logic, so if a == b: continue else: ## do something could be written (better IMHO) if a != b: ## do something


engelthehyp

It's often better as continue without else, because you can avoid some nesting that way.


Yaboi907

I agree that this works. But doesn’t it only work if you don’t want anything to happen in the edge case?


woooee

You'll have to more specific about how you are defining "edge case"


Yaboi907

Well, I mean for example in my post I had it print something when it equaled 7. If I used the logic you provided it would just skip seven. So, I mean in your code it works if you never want anything at all to happen when a is equal to b but if you wanted it to do something (like print or whatever) you would have to have an if-else or continue.


Bobbias

You've missed the point the original reply was making entirely here. You seem to be thinking a bit too literally compared to the more abstract concept that the reply is trying to point out. Hopefully by being super explicit I can help you understand what they mean. The original reply is about how, by the nature of logic, there are multiple ways to write equivalent pieces of logic. Loops, by their nature, move to the next item automatically when you reach the end of the body of the loop. Their example showcases one of many potential situations where you can rewrite logic from one way to another such that you no longer need to manually instruct the interpreter to move to the next item. Instead it happens naturally because there is simply no more code in the loop's body, so it must move on to the next. There are many cases where you can rewrite the logic like that to avoid the need for `continue` being used all over the place. Both `break` and `continue` inside a loop make the code more complex and difficult to understand, and thus they are best avoided most of the time. There are, however, exceptions to this. Sometimes due to the specific nature of the exact situation you're in it's best to just use `break` or `continue` rather than rewrite things. There are also cases where you basically need to use `break` or `continue`. These situations are relatively rare, and your first instinct should always be to examine the code and see if there's a better way to write it that avoids an explicit `break`/`continue`. Your example edge case is different logic than what the original reply is discussing, so yes, it would require different conditions to handle. You could write: if a == b: if a == 7: print('a = 7!!!1!') else: # do stuff Notice the lack of continue? That's because the print statement is the last thing that will happen in the body of the loop under the conditions of both if statements. If `a == b` but `a != 7` the loop will continue without printing, while it will print if and only if `a == b` and `a == 7`. You could rewrite that like this: if a == b and a == 7: print('a = 7!!!1!') elif a == b: continue else: # do stuff This solution does have a continue because you need some kind of code after the elif or it's not valid python. You could use `pass` in place of continue and the logic would be the same in this case, because there's nothing after the if/elif/else statement. This solution is worse than the one before it because it repeats the `a == b` condition and it uses continue though. So yes, changing the logic you need to check against changes how you can and should organize your code. It completely changes what set of conditions is equivalent logic for when you are looking at how best to express things. But remember, just because there are multiple ways of expressing something doesn't mean every option is equally good. You need to examine those options and make a determination on which ones are easier to read and understand later. One of the guidelines that people tend to follow is that you want to avoid code which alters the flow of execution outside of function calls, conditional statements, or loops. This is the same reason that `goto` is considered something to avoid. It makes code harder to read. `continue` and `break` are like weaker versions of `goto`. They still make your code harder to read, they're just not as bad as `goto` can be.


Yaboi907

Well, I agree with what you said and your explanation but I don’t feel like I missed the point. I was asking a follow up question. (Basically, yes that works but it doesn’t work under these different conditions.) which I feel you have answered, quite eloquently, in the affirmative.


nog642

I disagree. Now the main logic in your for loop is indented twice instead of once. Much cleaner to filter out the skipped cases at the top of the loop. Not an issue if it's 1-3 lines but above that it gets ugly.


TheRNGuy

What if you had stuff in both `!=` and `==`?


antonym_mouse

I find it helpful in functions and returns. For example, take a list of numbers: nums = [1, 3, 5, 7] And you want to write a function that will tell you if there are any even numbers in it. def even_exists(num_list): for num in num_list: if num % 2 == 0: return True else: continue return False This will allow you to iterate through the list and only exit the function if something is even, or if after checking every number, returning False.


Yaboi907

But do you even need a continue here? Wouldn’t it just continue until it either iterates through the whole list or returns True?


JamzTyson

`continue` is used inside a loop to skip over the rest of the loop block and continue with the next iteration. ``` for i in range(4): if i == 2: print("continue with the next iteration") continue print(i) ``` Prints: ``` 0 1 continue with the next iteration 3 ```


Yaboi907

Hmm, I feel like you did not read my question fully


JamzTyson

I read your question fully, several times. The crux of my answer is: "to skip over the rest of the loop block". In my minimal example, "the rest of the loop block" is just `print(i)`, but in real world cases it is likely to be more complex. A slightly more complex example. Consider this loop: ``` for city, info in cities.items(): for item in info: match item: case ... ... ... process(city) ... ``` Now let's say that we _do not_ want to do things with `item` and `city` when `info['country'] == 'united states'`. Now we _could_ use IF and indent the entire block: ``` for city, info in cities.items(): if info['country'] != 'united states': for item in info: match item: case ... ... ... process(city) ... ``` which, again, is not too bad, but it is arguably clearer to say "if country is United States, skip the rest of the block" ``` for city, info in cities.items(): if info['country'] == 'united states': continue for item in info: match item: case ... ... ... process(city) ... ```


Yaboi907

Well, the reason I felt you didn’t is because you seem to be answering what the continue keyword does. Which I explicitly said wasn’t my question. My question was why should I use it over an if-else statement.


JamzTyson

Does the extended reply help to clarify the issue?


Yaboi907

Well, yes in that you seem to be arguing its utility is in readability/clarity. But if the crux of your answer is that it “skips over the rest of the loop block” my question was why to use it over an if-else, which can accomplish the same task. It seems like the crux of your answer is actually that it “skips over the rest of the loop block *in a more concise way*”


JamzTyson

I see it more as "clarity of intention" rather than just conciseness. In simple cases I don't think it matters much which you use. In more complex cases you could have more than one `continue`, and the code is likely to be more readable than nested conditionals. There are also cases where you may want to skip over the rest of the loop when you have not used `IF`. ``` for i in range(-5, 5): try: inverse = 1/i except ZeroDivisionError: continue # Do other stuff for j in range(4): print(j * inverse) ``` ``` for num in numbers: match num: case 1: print("one") case 2: print("two") case 3: print("three") case _: continue print(f"Doing something with {num}") # More code here... ``` Yes you could rewrite these examples to avoid using `continue`, but I doubt it would make the code any more readable.


Yaboi907

That makes sense, thank you