Register to get access to free programming courses with interactive exercises

List generators Python: Declarative programming

In a developer's everyday life, you will often see code that works with iterations because iterators are built into the language and tightly integrated into the standard library.

We usually assemble iterators and operations on them into data conveyors. Only at the end of each pipeline is reduce() or something else that doesn't pass elements on. Most of these pipelines consist of two types of operations:

  1. Converting individual elements with the map() function. It converts the entire stream using another function that handles the individual items
  2. Changing the composition of the elements via filtration or multiplication. The filter() function can filter the data. And the map() paired with the chain() from the itertools module turns each element into several without changing the nesting level

For example, imagine we want a list of numbers like this:

[0, 0, 2, 2, 4, 4...]

There are two copies each of increasing even numbers. Let's write a suitable pipeline:

# Getting a stream of even numbers
def is_even(x):
    return x % 2 == 0

list(filter(is_even, range(20)))
# [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

# Doubling each of them
def dup(x):
    return [x, x]

list(map(dup, filter(is_even, range(20))))
# [[0, 0], [2, 2], [4, 4], [6, 6], [8, 8], [10, 10], [12, 12], [14, 14], [16, 16], [18, 18]]

# Making the pipeline flat again
from itertools import chain
list(chain(*map(dup, filter(is_even, range(20)))))
# [0, 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 16, 16, 18, 18]

# Making a single-line variant
list(chain(*map(lambda x: [x, x], filter(lambda x: x % 2 == 0, range(20)))))
# [0, 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 16, 16, 18, 18]

As you can see, the task is done by connecting ready-made elements rather than by writing all the code manually in the form of a for loop. We can already see the issue with our constructor: if there are no ready-made functions on elements or predicates, we will declare them beforehand or use lambda. Both options are inconvenient.

When another person reads our code with individual functions, they have to keep jumping back and forth through the code. And lambda looks unwieldy. But don't despair, Python has a syntax that can simplify working with conveyors.

Sign up

Programming courses for beginners and experienced developers. Start training for free

  • 130 courses, 2000+ hours of theory
  • 1000 practical tasks in a browser
  • 360 000 students
By sending this form, you agree to our Personal Policy and Service Conditions

Our graduates work in companies:

<span class="translation_missing" title="translation missing:">Bookmate</span>
<span class="translation_missing" title="translation missing:">Healthsamurai</span>
<span class="translation_missing" title="translation missing:">Dualboot</span>
<span class="translation_missing" title="translation missing:">Abbyy</span>
Suggested learning programs
Developing web applications with Django
10 months
from scratch
under development
Start at any time

Use Hexlet to the fullest extent!

  • Ask questions about the lesson
  • Test your knowledge in quizzes
  • Practice in your browser
  • Track your progress

Sign up or sign in

By sending this form, you agree to our Personal Policy and Service Conditions
Toto Image

Ask questions if you want to discuss a theory or an exercise. Hexlet Support Team and experienced community members can help find answers and solve a problem.