List comprehensions, break-continue, exception handling in Python
As we have learned for loop to walk through a sequence, and do something with each item, at least read some value from it.
There is a scenario, similar to what we saw with the last example in the for-loop introduction, that involves making a new list from the result of doing an operation on each item in that list.
We call this construct a list comprehension, and it builds on the syntax of a list. An example of a list comprehension is:
Another example is:
And list comprehensions also allow us to use conditions. We can have an if clause to test a condition and only add a result to the list if condition is true. For example:
We can also iterate this on multiple items for example:
With list comprehension we can also do above operation in one line of code:
The iterable can be any iterable object, like a list, tuple, set etc.
Same example with condition:
The expression is the current item in the iteration, but it is also the outcome, which you can manipulate before it ends up like a list item in the new list:
The expression can also contain conditions, not like a filter, but as a way to manipulate the outcome:
The break statement
We have mentioned the break statement when discussing an infinite loop. The break statement is used only inside a loop, to stop the execution of the looping statement when needed, even if the loop condition is still true (in the case of while loop) or the last member of the sequence has not been reached.
Here is an example where we break out of the loop that iterates over the list when we reach the ‘Bangalore’ city:
Note the subtle difference in the output, if you place the print(i) after the break statement, as follows:
In the case, Bangalore is not in the output because; the break happens before the iteration variable takes that value.
Let’s see another example, where we break out of the loop while searching for a number in a sequence. We break when the number to search is found, as there is no point in iterating over the remaining list.
Using Break in Nested Loops
In the above example, you saw two lists with four integer values in each. It then used two for loops to iterate through the lists and multiply the integers. Next, it defined the break conditions. When the break condition was met, the innermost loop was terminated, and the control went back to the outer loop.
The continue statement
Let’s see an example to illustrate what the continue statement does.
Sometimes, in a loop, we may have an if statement to test a condition for the current step of the loop, and if the condition is true, we want to do nothing. So basically, we would write code as follows:
Now, that was just a start. What we want, instead of printing we do nothing, which is like actually doing something, is to have no visible effect at all.
Here is where the continue statement is useful. We can use it instead of the line that was doing the printing, and the only other changes are: we remove the else line while keeping the instruction it was branching, and do an-indentation so that the block is aligned with the entire if block.
The previous code example becomes:
Some other examples:
The pass statement
The pass statement is an interesting feature of Python: a statement that tells the interpreter to do nothing. Ok, but what’s the point? Well, again, the typical use is in an if block where you do not want to produce any result yet.
So, at least semantically, we could use this trick for the example we previously discussed, before choosing to use the continue trick. The code would be as follow:
But wait, there in more to Remember, earlier I said you do not want to add code that produces result yet. And yes, you use pass instead of opting for using continue, if you are still writing/testing your code and you anticipate that, in the near term you would add some specific code in that if block. So, it is like, you are making progress structuring your code, putting skeleton in place, which you want to already be testable and partially producing the target functionality,
It is common for a developer to have several if…else blocks where the only instruction is a pass statement, preparing things for later branching the required those conditions. This makes agile and productive.
So yes, the pass statement could look not a big deal, but it is very useful productive programmer.
Now, we will cover the set of tools python offers us to handle errors: Exceptions.
Python uses exceptions to handle exceptional/unexpected situations while running your script and will throw them at you when they happen. This allows you to get a specific error message automatically, allowing you to fix the problem right away and move forward.
And when an error occurs, the reason behind can be very specific. That’s why a specific exception is raised. Using this mechanism, the programmer can catch the execution and output of a user-friendly error message or even continue the program flow. Depending on the type of execution.
There is a set of built-in or standard exceptions and a programmer can define a custom exception using Python’s object-oriented programming techniques.
Python standard exceptions
Python has Exception class which is the base class for all built-in exceptions. All of the built-in exceptions are derived from this class.
Let’s present a few common exception types in python.
- The SyntaxError exception is raised when the interpreter finds a syntax error while parsing the code.
- The ZeroDivisionError exception is raised when the divider in a division or modulo operation is 0, a situation that is not allowed.
- The ValueError exception is raised when a built-in operation or function receives an argument that has an inappropriate value.
- The KeyboardInterrupt exception is interesting. It is raised when the user hits the interrupt key (using Ctrl + c).
- The NameError exception is raised when a local or global name is not found.
Raising an exception
Though by default an exception is raised when an error has occurred. You can explicitly raise an exception in you code by using the raise statement (followed by exception object)
Here is an example:
When executing the code, we got the above output.
Raising an exception is an important technique. When dealing with complex use cases, the programmer can use it to make things more explicit, which is better to avoid bugs and help for future debug if needed. A developer writing code that would call the piece of code, could catch the exception using a special statement we will see in a minute, and limit the impact of the error on the user (showing a more user-friendly error message and/or doing something else when that error occurs).
When writing code that can be fragile, depending on what a line or a block of code.
is doing, we can try…except syntax to catch an exception that could be raised in some situations, depending on some input or our code’s execution environment. That is what exception handling is about.
We encapsulate the block or the line of code where the error might happen, with the try…except technique, as follows:
Here what we are doing is use the base Exception class, so we will catch any type of exception. If we wanted to catch only ValueError exceptions for example, we would do:
Let’s see how it goes. With rea code, building on a previous example. We catch the ValueError exception that is raised inside the code block; you guessed it, using the ValueError type. That way our exception handling is precise, and that is better to write solid code.
As we can see, the exception was handled, and as a user of the program. We did not notice the effect of the error condition.
That small example what exceptions and exception handling offer. Of course, instead of doing nothing when the exception is raised, using the pass statement, you can choose to write code that does something useful in that situation.