Python: Comprehensions

Comprehensions (and list comprehensions in particular) are probably the feature I love the most coming from JavaScript to Python. It enables you to write concise code for something you do very often: Iterating over a list, modifying the data a bit ("data massaging") and returning a list with the new entries.

One thing to note: List comprehension load the entire output into memory so this should only be used for small to medium-sized lists. In cases of big lists, use generators instead.

Basic Syntax (for lists):

[expression for item in iterable if conditional]

If you want to try the instructions below you can fire up the Python REPL. If you have Python installed run python in your terminal. Any Python code that starts with >>> symbols indicated that it was typed into a REPL.
To try out the JavaScript snippets you could use Quokka.js in your editor.

Examples

Iterating over the array and giving out the length of the word itself into a new list:

const names = ["James", "Naomi", "Amos", "Alex", "Bobbie", "Clarissa"]
const len_names = names.map((name) => name.length)
console.log(len_names)
// [ 5, 5, 4, 4, 6, 8 ]
>>> names = ["James", "Naomi", "Amos", "Alex", "Bobbie", "Clarissa"]
>>> len_names = [len(name) for name in names]
>>> print(len_names)
[5, 5, 4, 4, 6, 8]

Skipping the first item & last item (by index) and creating a list of dictionaries:

const names = ["James", "Naomi", "Amos", "Alex", "Bobbie", "Clarissa"]
const names_list = names
  .filter((_, id) => id !== 0 && id !== names.length - 1)
  .map((name) => ({ name, length: name.length }))
console.log(names_list)
// [ { name: 'Naomi', length: 5 }, { name: 'Amos', length: 4 }, { name: 'Alex', length: 4 }, { name: 'Bobbie', length: 6 } ]
>>> names = ["James", "Naomi", "Amos", "Alex", "Bobbie", "Clarissa"]
>>> names_list = [{ "name": name, "length": len(name) } for idx, name in enumerate(names) if idx != 0 and idx != len(names)-1]
>>> print(names_list)
[{'name': 'Naomi', 'length': 5}, {'name': 'Amos', 'length': 4}, {'name': 'Alex', 'length': 4}, {'name': 'Bobbie', 'length': 6}]

Tuple unpacking:

const students = [
  ["James", 16],
  ["Naomi", 20],
]
const nameWithAge = students.map((s) => [s[0].length + s[1], ...s])
console.log(nameWithAge)
// [ [ 21, 'James', 16 ], [ 25, 'Naomi', 20 ] ]
>>> students = [("James", 16), ("Naomi", 20)]
>>> nameWithAge = [[len(s[0])+s[1], *s] for s in students]
>>> print(nameWithAge)
[[21, 'James', 16], [25, 'Naomi', 20]]

Creating a list of characters from a string:

const myName = "LekoArts"
const arr = [...myName]
console.log(arr)
// [ 'L', 'e', 'k', 'o', 'A', 'r', 't', 's' ]
>>> my_name = 'LekoArts'
>>> arr = [l for l in my_name]
>>> print(arr)
['L', 'e', 'k', 'o', 'A', 'r', 't', 's']

Reversing strings in a tuple and returning them as a list:

const words = ["kayak", "LekoArts", "radar", "python"]
const reversed = words.map((word) => word.split("").reverse().join(""))
console.log(reversed)
// [ 'kayak', 'strAokeL', 'radar', 'nohtyp' ]
>>> words = ("kayak", "LekoArts", "radar", "python")
>>> reversed = [word[::-1] for word in words]
>>> print(reversed)
['kayak', 'strAokeL', 'radar', 'nohtyp']

You can also nest comprehensions. Here's a 3 by 3 identity matrix:

>>> matrix = [[1 if item_idx == row_idx else 0 for item_idx in range(0, 3)] for row_idx in range(0, 3)]
>>> print(matrix)
[[1, 0, 0], [0, 1, 0], [0, 0, 1]]

20