DEV Community

Cover image for The Proficient Pythonista: List Comprehensions
Joy Adaeze Uchenna
Joy Adaeze Uchenna

Posted on • Updated on

The Proficient Pythonista: List Comprehensions

For loops are a thing! But if you could sometimes use a construct that is way more concise and efficient won’t you go for it? Hell Yeah!!!

List comprehensions give us a succinct way to create lists based on existing lists.

To create a new list of numbers from an existing list using a for loop construct:

What if I told you what we have in the loop above can be done in just a single line code! - This is the power of list comprehensions. Take a look below in 2.py:

The structure for the code written in 2.py above is [ output expression for iterator variable in iterable ]:

  • number + 3 is the output expression - the result returned
  • number is the iterator variable
  • numbers is the iterable

List comprehension can be written over any iterable like a range object and not just lists as below:

We can also have conditionals in list comprehensions which helps filter what we get returned - it controls what items from an existing list are returned. This conditional logic can be on the iterator variable or the output expression.

In 4.py below is an example of a conditional logic used on the iterator variable, where it returns only items that are not equivalent to the string cisco:

In 4.py above, the structure for the code written is [output expression for iterator variable in iterable if predicate expression ] -

  • If flash != ‘cisco’ - the conditional logic which is an if predicate expression

Let’s take it further by having nested if predicate expressions within a list comprehension:

In 5.py above, it checks to see if the number num is divisible by 2 and then 4, and prints it out if it satisfies both conditions.

Moving on to conditionals on the output expression, let us see an example below:

The structure for the code written in 6.py above is [conditional on output expression for iterator variable in iterable] -

  • hero if len(hero)>=8 else '' - the conditional logic - outputs hero if the length of the string hero is less than 8, else it outputs an empty string.

Like list comprehensions, we can also have a dictionary comprehension or even a set comprehension. This is getting quite interesting right?

With set comprehensions, the output returned unlike a list comprehension contains no duplicates. Let’s see an example in 7.py below:

In 7.py, no duplicates are returned. Also, note that sets like dictionaries but unlike lists are inherently unordered - the order of items is not important - this is why o comes first in the set even if e is the first character in cool_quote.

Talking about dictionaries, let’s see an example of how we can use a dictionary comprehension to create a dictionary below:

In 8.py above, we have a key and value pair separated by a colon (:) - the keys are the items of the list while the values are the length of the items in the list.

Nested loops are also something we do sometimes. See an example below:

The code above is multiplying the items in the first list by the items in the second list. To write this in a list comprehension, it is written as below:

In 10.py above, the outer list comprehension [... for i in range(5, 8)] creates 3 rows, while the inner list comprehension [i*j for j in range(1,3)] fills these rows with values i.e i*j.

Very good use of list comprehension is to flatten a list consisting of multiple lists as seen below:

List comprehensions are superb! But I think you can still use for loops in certain places where code readability is key because it is important to also write what your team can read easily. I hope you are excited about your journey to becoming a Proficient Pythonista!!! 😉

Stay tuned to this series for my next article on GENERATORS! Have an amazing and fulfilled week ahead!

Top comments (10)

Collapse
 
sobolevn profile image
Nikita Sobolev

Great article! Thanks a lot!

It is also important to lint your python code generally (and list comprehensions in particular). Because they can contain different problems:

  1. x = (yield a for a in [1, 2, 3]) will be not what you might think it is. Linter can catch this!
  2. x = [lambda y: a + y for a in [1, 2, 3]] will return 4 for x[0](1). And good linter will also catch this error
  3. Good linter will enforce consistency in for a in [1, 2, 3], for a in {1, 2, 3} and for a in (1, 2, 3)
  4. Good linter will catch that for loop part has correct unpacking targets
  5. Great linter will warn you when you comprehensions are too complex
  6. Great linter will tell you that you comprehension is incorrect: like list([x for x in [1, 2, 3]])

I recommend to use wemake-python-styleguide. Check it out:

GitHub logo wemake-services / wemake-python-styleguide

The strictest and most opinionated python linter ever!

wemake-python-styleguide

wemake.services Supporters Build Status Coverage Status Python Version wemake-python-styleguide


Welcome to the strictest and most opinionated python linter ever.

wemake-python-styleguide logo

wemake-python-styleguide is actually a flake8 plugin with some other plugins as dependencies.

Quickstart

pip install wemake-python-styleguide

You will also need to create a setup.cfg file with the configuration.

We highly recommend to also use:

  • flakehell for easy integration into a legacy codebase
  • nitpick for sharing and validating configuration across multiple projects

Running

flake8 your_module.py

This app is still just good old flake8 And it won't change your existing workflow.

invocation resuts

See "Usage" section in the docs for examples and integrations.

We also support Github Actions as first class-citizens Try it out!

What we are about

The ultimate goal of this project is to make all people write exactly the same python code.

flake8 pylint black mypy wemake-python-styleguide
Formats code?
Finds style issues? 🤔 🤔
Finds bugs? 🤔
Collapse
 
mburszley profile image
Maximilian Burszley

It's not about consistency, it's about use-case. A list, tuple and set all solve different problems. Comprehensions should always be simple, otherwise you should be using a different construct that is readable.

Yes, you should use a linter, but almost any editor nowadays will catch the errors you point out and are not necessarily linting issues.

Collapse
 
brumelove profile image
Brume

You are a good teacher, easy to understand.

Collapse
 
joyadauche profile image
Joy Adaeze Uchenna

Thank you @brumelove

Collapse
 
cynchizy profile image
Abu Cynthia

Awesome write up, every detail was explicitly outline. I can't wait for your post on Generators

Collapse
 
joyadauche profile image
Joy Adaeze Uchenna

Glad you like it! Thanks @cynchizy

Collapse
 
bcbreeden profile image
Brian Breeden

List comprehensions are awesome, thank you for sharing!

Collapse
 
joyadauche profile image
Joy Adaeze Uchenna

You are welcome @bcbreeden

Collapse
 
shulugh profile image
Sesugh Hulugh

Simple and concise. Thanks

Collapse
 
joyadauche profile image
Joy Adaeze Uchenna

You are welcome. Glad you find it simple @shulugh