>> [i**2 for i in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
```
这将创建和对生成器理解输入调用 `list` 函数一样的结果。但是,使用列表理解比将生成器理解输入到 `list` 中稍微更高效一点。
让我们来体会一下列表理解的实惠之处。以下代码将在一个列表中储存包含字母“o”的字符串:
```python
words_with_o = []
word_collection = ['Python', 'Like', 'You', 'Mean', 'It']
for word in word_collection:
if "o" in word.lower():
words_with_o.append(word)
```
你可以使用列表理解来将以上代码在一行中实现:
```python
>>> word_collection = ['Python', 'Like', 'You', 'Mean', 'It']
>>> words_with_o = [word for word in word_collection if "o" in word.lower()]
>>> words_with_o
['Python', 'You']
```
你也可以用理解语句来创建元组,但是你必须要使用 `tuple` 构造器来做到这一点,因为括号已经为生成器理解保留了。
```python
# 使用理解表达式来创建元组
>>> tuple(i**2 for i in range(5))
(0, 1, 4, 9, 16)
```
**经验**:
理解语句是对创建简单或复杂的列表或元组都极其有用的语法。
### 嵌套理解语句
你可以在一个理解表达式中嵌套(nest)另外一个理解表达式,但请注意不要滥用这一功能。
```python
# 嵌套列表理解。
# 这创建了一个大小为3x4,内容为0的的“矩阵”(存有多个列表的列表)。
>>> [[0 for col in range(4)] for row in range(3)]
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
```
**阅读理解:列表理解**:
使用列表理解来的创建一个包含100个字符串“hello”的列表。
**阅读理解:高级的列表理解**:
使用单行的 `if-else` 语句(在本模组前文讨论过)以及列表理解来创建以下列表:
```python
['hello',
'goodbye',
'hello',
'goodbye',
'hello',
'goodbye',
'hello',
'goodbye',
'hello',
'goodbye']
```
**阅读理解:元组理解**:
使用元组理解来提取字符串中由逗号隔开的数字,并将它们转化成一个浮点数元组。比如说,`"3.2,2.4,99.8"` 应被转化成 `(3.2, 2.4, 99.8)`。你应该会想要使用内置的字符串函数[str.split](https://docs.python.org/3/library/stdtypes.html#str.split)。
**阅读理解:翻译for循环**:
使用列表理解来复制以下代码的功能。
```python
# 跳过所有非小写字母(包括标点符号)
# 如果小写字母是“o”,在列表结尾添加1
# 如果小写字母不是“o”,在列表结尾添加0
out = []
for i in "Hello. How Are You?":
if i.islower():
out.append(1 if i is "o" else 0)
```
**阅读理解:内存效率**:
以下两个表达式的效率有任何区别么?
```python
# 将生成器理解输入到 `sum` 中
sum(1/n for n in range(1, 101))
```
```python
# 将列表理解输入到 `sum` 中
sum([1/n for n in range(1, 101)])
```
以上有一个表达式优于另外一个吗?为什么?
## 官方说明文档链接
- [生成器定义](https://docs.python.org/3/glossary.html#term-generator)
- [range](https://docs.python.org/3/library/stdtypes.html#typesseq-range)
- [生成器理解表达式](https://docs.python.org/3/tutorial/classes.html#generator-expressions)
- [迭代器定义](https://docs.python.org/3/glossary.html#term-iterator)
- [next](https://docs.python.org/3/library/functions.html#next)
- [iter](https://docs.python.org/3/library/functions.html#iter)
- [列表理解](https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions)
- [嵌套列表理解](https://docs.python.org/3/tutorial/datastructures.html#nested-list-comprehensions)
## 阅读理解答案:
**使用 `range`:解**
```python
# start=10,stop=0(不包含),step-size=-1
>>> for i in range(10, 0, -1):
>>> print(i, end=" ") # “end”参数用来避免每个值都使用新行打印
10 9 8 7 6 5 4 3 2 1
```
**编写生成器理解:解**
```python
>>> g = ((n, n+2) for n in range(6) if n != 3)
>>> list(g) # 转化成列表来打印其中的值
[(0, 2), (1, 3), (2, 4), (4, 6), (5, 7)]
```
**直接使用生成器理解:解**
```python
>>> sum(range(1, 101, 2))
2500
```
或
```python
>>> sum(i for i in range(101) if i%2 != 0)
2500
```
**列表理解:解**
```python
>>> ["hello" for i in range(100)]
['hello', 'hello', ..., 'hello', 'hello'] # 100个hello
```
**高级的列表理解:解**
```python
>>> [("hello" if i%2 == 0 else "goodbye") for i in range(10)]
['hello', 'goodbye', 'hello', 'goodbye', 'hello', 'goodbye', 'hello', 'goodbye', 'hello', 'goodbye']
```
**元组理解:解**
```python
>>> string_of_nums = "3.2, 2.4, 99.8"
>>> tuple(float(i) for i in string_of_nums.split(","))
(3.2, 2.4, 99.8)
```
**翻译for循环:解**
```python
>>> out = [(1 if i is "o" else 0) for i in "Hello. How Are You?" if i.islower()]
>>> out
[0, 0, 0, 1, 1, 0, 0, 0, 1, 0]
```
**内存效率:解**
生成器表达式 `sum(1/n for n in range(1, 101))` 比起列表理解 `sum([1/n for n in range(1, 101)])` 更优。使用列表理解会不必要的在内存中创建有100个数字的列表,然后再将其输入到 `sum` 中。生成器表达式则在 `sum` 迭代时每次只生成一个数值。