-
List, Dictionary, Set Comprehensions, and Difference between List Comprehensions and Generator expressionsDynamicPL/Python 2019. 10. 22. 16:56
1. Overview
After reading this article you’ll learn:
- What are the list comprehensions in Python
- What are set comprehensions and dictionary comprehensions
2. Definition
List comprehensions provide us with a simple way to create a list based on some iterable. During the creation, elements from the iterable can be conditionally included in the new list and transformed as needed. An iterable is something you can loop over.
The components of a list comprehension are:
- Output Expression (Optional)
- Iterable
- Iterator variable which represents the members of the iterable
numbers = [1, 2, 3, 4, 5, 6, 18, 20] squares = ["small" if number < 10 else "big" for number in numbers if number % 2 == 0 if number % 3 == 0] print(squares) #output ['small', 'big']
3. Comparison between List Comprehensions and loops
The list comprehensions are more efficient both computationally and in terms of coding space and time than a for a loop. Typically, they are written in a single line of code.
Let’s see how much more space we’ll need to get the same result from the last example using a for a loop.
3.1 Convertable
Every list comprehension can be rewritten as a for loop, but not every for loop can be rewritten as a list comprehension.
3.2 Speed
import timeit def squares(size): result = [] for number in range(size): result.append(number*number) return result def squares_comprehension(size): return [number*number for number in range(size)] print(timeit.timeit("squares(50)", "from __main__ import squares", number = 1_000_000)) print(timeit.timeit("squares_comprehension(50)", "from __main__ import squares_comprehension", number = 1_000_000)) #output 6.255051373276501 3.7140220287915326
The list comprehension implementation will be faster in all cases.
3.3 Readability
numbers = [1, 2, 3, 4, 5, 6, 18, 20] squares = [ "small" if number < 10 else "big" for number in numbers if number % 2 == 0 if number % 3 == 0] print(squares) #output ['small', 'big']
3.4 Nested Feature
3.4.1 Nested For Loops
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] flattened = [] for row in matrix: for item in row: flattened.append(item) print(flattened) #output [1, 2, 3, 4, 5, 6, 7, 8, 9]
We can achieve the same result using a list comprehension.
Tip: the order of the for clauses remain the same as in the original for loops.matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] flattened = [item for row in matrix for item in row] print(flattened) #output [1, 2, 3, 4, 5, 6, 7, 8, 9]
3.4.2 Nested List Comprehensions
matrix = [[item for item in range(5)] for row in range(3)] print(matrix) #output [[0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4]]
The "range" type represents an immutable sequence of numbers and is commonly used for looping a specific number of times in "for" loops
3.5 Comparison between List Comprehensions and map and filter
List comprehensions are a concise notation borrowed from the functional programming language Haskell. We can think of them like syntactic sugar for the filter and map functions.
We have seen that list comprehensions can be a good alternative to "for" loops because they are more compact and faster.
3.5.1 Lambda Function
Lambda functions are small anonymous functions. They can have any number of arguments but can have only one expression.
Mostly, the lambda functions are passed as parameters to functions which expect a function object as one of their parameters like map and filter.
3.5.2 Map Function
The map function returns an iterator that applies a function to every item of iterable, yielding the results. Let’s compare it with a list comprehension.
# Map numbers = [1, 2, 3, 4, 5] squares = list(map(lambda x: x**2, numbers)) print(squares) # List Comprehension numbers = [1, 2, 3, 4, 5] squares = [number**2 for number in numbers] print(squares) #output [1, 4, 9, 16, 25] [1, 4, 9, 16, 25]
3.5.3 Filter Function
# Filter numbers = [1, 2, 3, 4, 5] filtered = list(filter(lambda x: x % 2 == 0, numbers)) print(filtered) # List Comprehension numbers = [1, 2, 3, 4, 5] filtered = [number for number in numbers if number % 2 == 0] print(filtered) #output [2, 4] [2, 4]
3.6 Other Comprehensions
In Python, we have also dictionary comprehensions and set comprehensions. All the principles we saw are the same for these comprehensions, too. We just have to know some very little details to create a dictionary or set comprehensions.
3.6.1 Dictionary Comprehensions
To create a dictionary comprehension we just need to change the brackets [] to curly braces {}. Additionally, in the output expression, we need to separate key and value by a colon : .
prices = {"beer": 2, "fish": 5, "apple": 1} float_prices = {key:float(value) for key, value in prices.items()} print(float_prices) #output {'beer': 2.0, 'fish': 5.0, 'apple': 1.0}
3.6.2 Set Comprehensions
To create a set comprehension we only need to change the brackets [] to curly braces {}.
numbers = [10, 10, 20, 30, 12, -20, 0, 1] unique_squares = {number**2 for number in numbers} print(unique_squares) #output {0, 1, 100, 144, 400, 900}
4. Generator expressions
Python also has something called generator expressions. They are very similar to the list comprehensions. The difference is that they use round brackets (). Also, they don’t store the list in memory. They use the lazy evaluation technique. And generator expression will be exhausted after one cycle.
List comprehensions aren’t useful if you’re working with iterators that return an infinite stream or a very large amount of data. Generator expressions are preferable in these situations.
5. Reference
https://towardsdatascience.com/python-basics-list-comprehensions-631278f22c40
'DynamicPL > Python' 카테고리의 다른 글
Slice (0) 2019.10.28 Sequence (0) 2019.10.26 iterator, iterable, iteration, iterator protocol, generator functions, generator expressions, and lazy evaluation (0) 2019.10.22 Asterisk(*) of Python (0) 2019.10.18 Data Structure in Python (0) 2019.10.18