Suppose you wanted to loop through a list of strings and print all the strings that are more than 3 characters long. You could do it like this:
values = ['a', 'bcd', 'efgh', 'pqrst', 'yz'] def longer_than_3(s): return len(s) > 3 for v in values: if longer_than_3(v): print(v) do_other_stuff()
longer_than_3 function returns true if the string is longer than 3 characters, or false otherwise. If it is true, we print the
string, and maybe do some other stuff. If it is false, we skip the entire body of the loop.
This code is fine as it is, but we could improve it slightly using the
filter function accepts a predicate, and a sequence of values. A predicate is a function that accepts a single parameter, and returns a boolean value. For example, our
longer_than_3 function is a predicate because it accepts a single paramter (a string) and returns True or False depending on whether the string has more than 3 characters.
filter applies the predicate to each item in the sequence, and returns a new sequence containing only those items for which the predicate returned true.
So how do we use
filter in a loop? Well, much the same as
reversed or any of the other loop functions, like this:
values = ['a', 'bcd', 'efgh', 'pqrst', 'yz'] def longer_than_3(s): return len(s) > 3 for v in filter(longer_than_3, values): print(v) do_other_stuff()
The advantage of using filter
Clearly, our code is now one line shorter. But the real advantage, as ever, is that it makes the intent of the code clearer.
filter function makes it totally clear that the filtering applies to the whole loop. It brings the filter functionality out
of the body of the loop and places it directly in
for statement itself.
On the other hand, the
if statement (in the original code at the start of the article) is a little more ambiguous. You need to
inspect the loop before deciding that the condition affects the entire loop body, rather than just part of it. This isn't too hard
with a simple two line loop body, but it is less obvious in complex code.
Using a lambda function
In this case, the function we are using is only a single line of code, so we can use a
lambda function instead of a function declaration. This definition creates an
unnamed lambda function equivalent to
lambda x: len(x) > 3
Here is how we use it in the code (notice that the
longer_than_3 function is no longer required):
values = ['a', 'bcd', 'efgh', 'pqrst', 'yz'] for v in filter(lambda x: len(x) > 3, values): print(v) do_other_stuff()
In summary, if you are writing a loop that only processes certain elements within the sequence, consider using a
for loop, rather than an
if statement in the body of the loop, to make the intent of the code clear.
If the selection criterion is a simple, one line function, consider using a lambda function for code brevity and readability.
- List comprehensions
- Objects and variables
- Objects and identity
- Immutable objects
- Global variables
- Data types
- Lists vs tuples
- Named tuples
- Short circuit evaluation
- Walrus Operator
- For loops
- For loop using range vs iterables
- Changing the loop order
- Using enumerate in a for loop
- Using zip in a for loop
- Looping over multiple items (old article)
- Declaring functions
- Calling functions
- Function objects and lambdas
- Function decorators
- With statements
- Exception handling
- String functions
- Built-in functions
- Optimisation good practice
- Low level code optimisation
- Structural optimisation
2d arrays abstract data type alignment and angle animation arc array arrays bar chart bar style behavioural pattern bezier curve built-in function callable object chain circle classes clipping close closure cmyk colour combinations comparison operator comprehension context context manager conversion count creational pattern data science data types decorator design pattern device space dictionary drawing duck typing efficiency ellipse else encryption enumerate fill filter font font style for loop formula function function composition function plot functools game development generativepy tutorial generator geometry gif global variable gradient greyscale higher order function hsl html image image processing imagesurface immutable object in operator index inner function input installing iter iterable iterator itertools join l system lambda function len lerp line line plot line style linear gradient linspace list list comprehension logical operator lru_cache magic method mandelbrot mandelbrot set map marker style matplotlib monad mutability named parameter numeric python numpy object open operator optimisation optional parameter or pandas partial application path pattern permutations pie chart polygon positional parameter print product programming paradigms programming techniques pure function python standard library radial gradient range recipes rectangle recursion reduce regular polygon repeat rgb rotation roundrect scaling scatter plot scipy sector segment sequence setup shape singleton slice slicing sound spirograph sprite square str stream string stroke structural pattern subpath symmetric encryption template text text metrics tinkerbell fractal transform translation transparency triangle truthy value tuple turtle unpacking user space vectorisation webserver website while loop zip zip_longest