38. Sự hiểu biết
#38. Sự hiểu biết
Sự hiểu biết là cú pháp nhỏ gọn để xây dựng các thùng chứa hoặc các trình vòng lặp giống như trình tạo từ một vòng lặp khác. CPython triển khai chúng dưới dạng đối tượng mã được biên dịch với phạm vi thực thi riêng.
Các hình thức phổ biến:python [x * 2 for x in xs] {x * 2 for x in xs} {x: x * 2 for x in xs} (x * 2 for x in xs) Những điều này tương ứng với:```text
list comprehension
set comprehension
dict comprehension
generator expression
## 38.1 Hiểu danh sách
Việc hiểu danh sách sẽ xây dựng một danh sách một cách háo hức.```python
ys = [x * 2 for x in xs]
```Về mặt khái niệm:```python
ys = []
for x in xs:
ys.append(x * 2)
```Kết quả là một đối tượng danh sách chứa tất cả các giá trị được tạo ra.
Biểu mẫu nguồn ngắn hơn nhưng công việc trong thời gian chạy vẫn là các thao tác lặp, đánh giá biểu thức và nối thêm.
## 38.2 Lọc
Sự hiểu biết có thể bao gồm một`if`khoản.```python
ys = [x * 2 for x in xs if x > 0]
```Về mặt khái niệm:```python
ys = []
for x in xs:
if x > 0:
ys.append(x * 2)
```Bộ lọc chạy cho từng mục. Nếu điều kiện sai thì biểu thức phần tử sẽ không chạy cho mục đó.
## 38.3 Nhiều`for`khoản
Sự hiểu biết có thể chứa các vòng lặp lồng nhau.```python
pairs = [(x, y) for x in xs for y in ys]
```Về mặt khái niệm:```python
pairs = []
for x in xs:
for y in ys:
pairs.append((x, y))
```Thứ tự từ trái sang phải, khớp với thứ tự vòng lặp lồng nhau.
Vì:```python
[(x, y, z) for x in xs for y in ys for z in zs]
```tổ vòng lặp khái niệm là:```python
result = []
for x in xs:
for y in ys:
for z in zs:
result.append((x, y, z))
```## 38.4 Nhiều bộ lọc
Bộ lọc gắn vào cấp độ vòng lặp nơi chúng xuất hiện.```python
result = [x for x in xs if x > 0 if x % 2 == 0]
```Về mặt khái niệm:```python
result = []
for x in xs:
if x > 0:
if x % 2 == 0:
result.append(x)
```Với nhiều vòng lặp:```python
result = [(x, y) for x in xs if x > 0 for y in ys if y > x]
```Về mặt khái niệm:```python
result = []
for x in xs:
if x > 0:
for y in ys:
if y > x:
result.append((x, y))
```Thứ tự quan trọng vì các mệnh đề sau có thể sử dụng các tên bị ràng buộc bởi các mệnh đề trước đó.
## 38.5 Phạm vi hiểu
Trong Python 3, việc hiểu có phạm vi riêng.```python
x = 100
ys = [x for x in range(3)]
print(x)
```Đầu ra:```text
100
```các`x`bên trong sự hiểu biết không ghi đè lên bên ngoài`x`.
Về mặt khái niệm, sự hiểu biết hoạt động giống như một hàm lồng nhau nhỏ:```python
def _listcomp(iterable):
result = []
for x in iterable:
result.append(x)
return result
ys = _listcomp(range(3))
```Đây không phải là sự chuyển đổi nguồn chính xác nhưng nó giải thích phạm vi.
## 38.6 Tại sao phần hiểu lại có đối tượng mã riêng
Một sự hiểu biết cần một nơi để lưu trữ các biến vòng lặp của nó mà không rò rỉ chúng ra phạm vi xung quanh.
CPython giải quyết vấn đề này bằng cách biên dịch nhiều phần hiểu thành các đối tượng mã lồng nhau.
Ví dụ:```python
def f(xs):
return [x * 2 for x in xs]
```Hàm bên ngoài có một đối tượng mã. Việc hiểu danh sách có một đối tượng mã khác được lưu trữ trong các hằng số của đối tượng mã bên ngoài.
Bạn có thể kiểm tra điều này:```python
def f(xs):
return [x * 2 for x in xs]
for const in f.__code__.co_consts:
print(type(const), const)
```Một hằng số thường là một đối tượng mã lồng nhau để dễ hiểu.
## 38.7 Phân tách sự hiểu biết về danh sách
sử dụng`dis`:
```python
import dis
def f(xs):
return [x * 2 for x in xs]
dis.dis(f)
```Sau đó kiểm tra các đối tượng mã lồng nhau:```python
for const in f.__code__.co_consts:
if hasattr(const, "co_code"):
dis.dis(const)
```Bạn sẽ thấy hai lớp:```text
outer function:
create comprehension function
get iterator from xs
call comprehension function
return list
inner comprehension:
build list
iterate input
compute x * 2
append to list
return list
```Mã byte chính xác thay đổi trên các phiên bản CPython, nhưng hình dạng vẫn giữ nguyên.
## 38.8 Tối ưu hóa việc nối thêm danh sách
Việc hiểu danh sách thường sử dụng một đường dẫn mã byte nối thêm danh sách chuyên biệt.
Về mặt khái niệm:```python
result.append(value)
```Nhưng CPython có thể tránh được việc tra cứu phương thức thông thường cho mỗi phần bổ sung.
Thay vì làm điều này cho từng mục:```text
load result.append
call append
```cơ quan hiểu có thể sử dụng thao tác chắp thêm nội bộ.
Về mặt khái niệm:```text
LIST_APPEND
```Điều này giúp tiết kiệm chi phí tra cứu thuộc tính và gọi phương thức lặp đi lặp lại.
Đây là một lý do khiến việc hiểu danh sách thường nhanh hơn các vòng lặp cấp Python tương đương với`append`.
## 38.9 Hiểu bộ
Sự hiểu biết về tập hợp sẽ xây dựng một tập hợp một cách háo hức.```python
unique = {x.lower() for x in words}
```Về mặt khái niệm:```python
unique = set()
for x in words:
unique.add(x.lower())
```Kết quả chứa các phần tử duy nhất theo phép băm và đẳng thức tập hợp thông thường.
Việc hiểu tập hợp sử dụng hành vi thêm tập hợp trong nội bộ, tương tự như cách hiểu danh sách sử dụng hành vi nối thêm.
## 38.10 Hiểu chính tả
Khả năng hiểu chính tả sẽ xây dựng một từ điển một cách háo hức.```python
index = {item.id: item for item in items}
```Về mặt khái niệm:```python
index = {}
for item in items:
index[item.id] = item
```Nếu khóa trùng lặp xuất hiện, các giá trị sau sẽ ghi đè các giá trị trước đó:```python
d = {x % 2: x for x in range(5)}
print(d)
```Đầu ra:```text
{0: 4, 1: 3}
```Việc hiểu tuân theo ngữ nghĩa phân công từ điển thông thường.
## 38.11 Trình tạo biểu thức
Một biểu thức của trình tạo là lười biếng.```python
g = (x * 2 for x in xs)
```Nó không xây dựng một danh sách ngay lập tức. Nó tạo ra một đối tượng giống như trình tạo để tính toán các giá trị khi lặp lại.```python
g = (x * 2 for x in range(3))
print(next(g))
print(next(g))
print(next(g))
```Đầu ra:```text
0
2
4
```Sau khi kiệt sức, nó tăng lên`StopIteration`.
## 38.12 Biểu thức trình tạo và hiểu danh sách
So sánh:```python
[x * 2 for x in xs]
```Và:```python
(x * 2 for x in xs)
```| Tính năng | Danh sách hiểu | Biểu thức máy phát điện |
|---|---|---|
| Đánh giá | Háo hức | Lười biếng |
| Kết quả | Danh sách | Đối tượng máy phát điện |
| Ký ức | Lưu trữ tất cả kết quả | Lưu trữ trạng thái thực thi |
| Lặp lại | Có thể lặp lại kết quả nhiều lần | Một lần |
| Cú pháp | Dấu ngoặc vuông | Dấu ngoặc đơn |
| Trường hợp sử dụng | Cần tất cả các giá trị ngay bây giờ | Giá trị luồng |
Việc hiểu danh sách thường nhanh hơn khi bạn cần danh sách đầy đủ.
Biểu thức trình tạo thường tốt hơn khi bạn muốn truyền phát các giá trị hoặc dừng sớm.
## 38.13 Bản chất một lần của biểu thức tạo
Một biểu thức trình tạo được sử dụng một lần.```python
g = (x for x in range(3))
print(list(g))
print(list(g))
```Đầu ra:```text
[0, 1, 2]
[]
```đầu tiên`list(g)`làm cạn kiệt nó.
Nếu bạn cần dữ liệu có thể tái sử dụng, hãy tạo danh sách hoặc vùng chứa khác.
## 38.14 Dừng sớm
Biểu thức của trình tạo rất hữu ích với người tiêu dùng dừng sớm.```python
first = next(x for x in xs if x > 100)
```Việc này chỉ tính toán cho đến khi tìm thấy phần tử phù hợp đầu tiên.
Một phiên bản hiểu danh sách:```python
first = [x for x in xs if x > 100][0]
```xây dựng danh sách đầy đủ các kết quả phù hợp trước khi chọn mục đầu tiên.
Đối với đầu vào lớn hoặc vô hạn, biểu thức trình tạo là mô hình chính xác.
## 38.15 Hiểu và kết thúc
Sự hiểu biết có thể nắm bắt các biến bên ngoài.```python
def scale(xs, factor):
return [x * factor for x in xs]
```Sự hiểu biết sử dụng`factor`từ chức năng bên ngoài.
Về mặt khái niệm:```text
outer function frame:
factor stored in local or cell
comprehension code object:
reads factor as free variable
```Trình biên dịch sắp xếp các ô đóng khi khả năng hiểu cần truy cập vào các biến phạm vi bên ngoài.
## 38.16 Liên kết biến vòng lặp
Biến vòng lặp thuộc phạm vi hiểu.```python
def f():
x = "outer"
ys = [x for x in range(3)]
return x, ys
print(f())
```Đầu ra:```text
('outer', [0, 1, 2])
```Bên trong sự hiểu biết,`x`là một cục bộ của đối tượng mã hiểu.
Bên ngoài`x`vẫn không thay đổi.
## 38.17 Biểu thức gán ở dạng hiểu
Biểu thức gán có thể xuất hiện trong phần hiểu.```python
result = [y for x in xs if (y := f(x)) > 0]
```Các quy tắc ràng buộc là tinh tế. Biểu thức gán liên kết trong phạm vi chứa, không phải trong phạm vi hiểu ngầm theo cách tương tự như biến vòng lặp.
Ví dụ:```python
def f(xs):
result = [y for x in xs if (y := x * 2) > 3]
return y, result
```Sau khi hiểu rõ,`y`có thể hiển thị trong phạm vi hàm chứa nếu xảy ra ít nhất một phép gán.
Hành vi này tồn tại vì các biểu thức gán được thiết kế để cung cấp tên được gán bên ngoài một số ngữ cảnh cục bộ của biểu thức.
## 38.18 Sự hiểu biết lồng nhau
Một sự hiểu biết có thể chứa đựng một sự hiểu biết khác.```python
matrix = [[i * j for j in range(3)] for i in range(3)]
```Về mặt khái niệm:```python
matrix = []
for i in range(3):
row = []
for j in range(3):
row.append(i * j)
matrix.append(row)
```Mỗi cách hiểu có đối tượng và phạm vi mã riêng.
Do đó, khả năng hiểu lồng nhau có thể tạo ra các lớp thực thi giống như hàm lồng nhau.
## 38.19 Hiểu Từ điển
Lặp lại một từ điển mang lại các khóa.```python
keys = [k for k in d]
```Để sử dụng các giá trị:```python
values = [v for v in d.values()]
```Để sử dụng cặp khóa-giá trị:```python
pairs = [(k, v) for k, v in d.items()]
```Một phép biến đổi chung:```python
inverted = {v: k for k, v in d.items()}
```Nếu các giá trị bị trùng lặp, các khóa sau sẽ ghi đè các khóa trước đó vì các khóa từ điển phải là duy nhất.
## 38.20 Thứ tự hiểu và đánh giá
Mệnh đề hiểu thực hiện từ trái sang phải.```python
[(x, y) for x in xs for y in f(x)]
```Đối với mỗi`x`, `f(x)`được đánh giá để tạo ra lần lặp bên trong.
Về mặt khái niệm:```python
result = []
for x in xs:
for y in f(x):
result.append((x, y))
```Điều này có nghĩa là các mệnh đề sau có thể phụ thuộc vào các biến vòng lặp trước đó.
Biểu thức phần tử chỉ chạy sau khi tất cả các mệnh đề vòng lặp và bộ lọc cho giá trị đầu ra đó đã thành công.
## 38.21 Tác dụng phụ
Sự hiểu biết có thể chứa đựng những tác dụng phụ, nhưng thường nên được sử dụng để tạo ra các giá trị.
Có thể nhưng phong cách kém:```python
[print(x) for x in xs]
```Điều này xây dựng một danh sách`None`giá trị chỉ để thực hiện in ấn.
Thích hơn:```python
for x in xs:
print(x)
```Sử dụng sự hiểu biết khi kết quả quan trọng.
## 38.22 Ngoại lệ trong cách hiểu
Các ngoại lệ lan truyền bình thường.```python
result = [10 / x for x in xs]
```Nếu như`x`bằng không,`ZeroDivisionError`lan truyền và sự hiểu biết dừng lại.
Các vùng chứa nội bộ được xây dựng một phần sẽ bị loại bỏ trừ khi được tham chiếu ở nơi khác, điều mà các phần nội bộ hiểu thông thường không tiết lộ.
Đối với các biểu thức của trình tạo, các ngoại lệ xảy ra một cách lười biếng:```python
g = (10 / x for x in xs)
```Tạo`g`không phân chia. Ngoại lệ xảy ra khi mục có vấn đề được yêu cầu.
## 38.23 Sự hiểu biết và`try`Sự hiểu biết không cho phép những phát biểu như`try`ngay bên trong chúng.
Không hợp lệ:```python
[x for x in xs try ...]
```Sử dụng chức năng trợ giúp:```python
def parse_or_none(x):
try:
return int(x)
except ValueError:
return None
values = [y for x in xs if (y := parse_or_none(x)) is not None]
```Hoặc sử dụng vòng lặp thông thường khi xử lý ngoại lệ là trung tâm:```python
values = []
for x in xs:
try:
values.append(int(x))
except ValueError:
pass
```## 38.24 Hiểu biết không đồng bộ
Bên trong`async def`, sự hiểu biết có thể sử dụng`async for`.
```python
async def collect(stream):
return [item async for item in stream]
```Về mặt khái niệm:```python
result = []
async for item in stream:
result.append(item)
return result
```Họ cũng có thể sử dụng`await`trong biểu thức phần tử hoặc bộ lọc:```python
async def collect(xs):
return [await process(x) for x in xs]
```Khả năng hiểu không đồng bộ sẽ biên dịch thành mã byte nhận biết không đồng bộ và có thể tạm dừng trong khi thực thi.
## 38.25 Biểu thức trình tạo không đồng bộ
Biểu thức trình tạo không đồng bộ có thể sử dụng`async for`.
```python
gen = (item async for item in stream)
```Nó tạo ra một đối tượng giống như trình tạo không đồng bộ được sử dụng với`async for`hoặc`anext`.
```python
async for item in gen:
...
```Mô hình thực thi kết hợp phạm vi hiểu với phép lặp không đồng bộ và tạm ngưng coroutine.
## 38.26 Sự hiểu biết và`locals()`Bởi vì sự hiểu biết có phạm vi riêng của nó,`locals()`bên trong một trình trợ giúp giống như hiểu sẽ nhìn thấy các biến cục bộ hiểu, không chính xác là các biến cục bộ xung quanh.
Điều này dễ thấy hơn với các hàm trợ giúp so với cú pháp trực tiếp vì khả năng hiểu hạn chế các câu lệnh.
Nguyên tắc quan trọng:```text
loop variables in comprehensions do not leak into the surrounding scope
```Đối với mã thông thường, hãy dựa vào quy tắc đó thay vì chi tiết về`locals()`bên trong các khung do triển khai thực hiện.
## 38.27 Hiểu biết và ràng buộc muộn
Việc đóng cửa bên trong sự hiểu biết vẫn có thể hiển thị hành vi ràng buộc muộn.```python
funcs = [lambda: x for x in range(3)]
print([f() for f in funcs])
```Đầu ra:```text
[2, 2, 2]
```Mỗi lambda đóng trên cùng một biến hiểu`x`, có giá trị cuối cùng là`2`.
Sử dụng đối số mặc định để nắm bắt giá trị hiện tại:```python
funcs = [lambda x=x: x for x in range(3)]
print([f() for f in funcs])
```Đầu ra:```text
[0, 1, 2]
```Phạm vi hiểu ngăn chặn sự rò rỉ ra bên ngoài, nhưng nó không tạo ra một ràng buộc mới cho mỗi lần lặp đối với các bao đóng.
## 38.28 Mức độ hiểu và thời gian tham khảo
Việc hiểu danh sách không giữ cho khung của nó tồn tại sau khi hoàn thành trừ khi có thứ gì đó nắm bắt được nó.
Tuy nhiên, biểu thức trình tạo vẫn giữ trạng thái giống khung của nó trong khi bị treo.```python
g = (x * 2 for x in range(10))
```Biểu thức trình tạo giữ:```text
code object
iteration state
current iterator
locals
suspended frame state
```Nếu nó bắt được một vật thể lớn, vật thể đó có thể vẫn còn sống cho đến khi máy phát điện cạn kiệt hoặc bị loại bỏ.```python
def f():
big = bytearray(100_000_000)
return (x for x in range(3) if big is not None)
g = f()
```Đây,`big`vẫn còn tồn tại thông qua việc đóng biểu thức trình tạo.
## 38.29 Hiểu biết và Hiệu suất
Việc hiểu danh sách thường nhanh hơn các vòng lặp tương đương vì CPython có thể sử dụng các hoạt động nội bộ chuyên biệt.
Ví dụ:```python
result = []
for x in xs:
result.append(x * 2)
```So sánh với:```python
result = [x * 2 for x in xs]
```Việc hiểu có thể tránh việc lặp lại việc tra cứu phương thức cấp Python cho`append`.
Tuy nhiên, hiệu suất phụ thuộc vào biểu thức, kích thước dữ liệu, phiên bản Python và liệu độ lười có quan trọng hay không.
Nguyên tắc chung:```text
use list/set/dict comprehensions when building that container directly
use generator expressions when streaming or stopping early
use explicit loops when control flow is complex
```## 38.30 Khả năng hiểu và dễ đọc
Sự hiểu biết rõ ràng nhất khi chúng phù hợp với một sự chuyển đổi đơn giản.
Tốt:```python
names = [user.name for user in users]
```Tốt:```python
active = [user for user in users if user.active]
```Thường quá dày đặc:```python
result = [(a, b, c) for a in xs if p(a) for b in f(a) if q(b) for c in g(a, b) if r(c)]
```Sử dụng vòng lặp rõ ràng khi có nhiều mệnh đề, tác dụng phụ, xử lý ngoại lệ hoặc phân nhánh phức tạp.
## 38,31 Luồng đối tượng CPython
Để hiểu danh sách:```python
[x * 2 for x in xs]
```CPython về mặt khái niệm thực hiện:```text
create result list
get iterator from xs
loop:
get next item
store item in comprehension local x
load x
load constant 2
multiply
append to result list
return result list
```Đối tượng danh sách được giữ bên trong khung hiểu trong khi nó đang được xây dựng.
Để hiểu chính tả:```python
{x: x * 2 for x in xs}
```dòng chảy là:```text
create result dict
iterate xs
compute key
compute value
store key-value pair
return dict
```## 38.32 Tên đối tượng mã hiểu
Các đối tượng mã hiểu có tên nội bộ như:```text
<listcomp>
<setcomp>
<dictcomp>
<genexpr>
```Bạn có thể nhìn thấy chúng trong quá trình truy nguyên và xem xét nội tâm.
Ví dụ:```python
def f(xs):
return [10 / x for x in xs]
f([2, 1, 0])
```Truy nguyên có thể bao gồm`<listcomp>`vì ngoại lệ xảy ra bên trong đối tượng mã hiểu.
Điều này cho thấy rằng việc thực thi hiểu có bối cảnh giống như khung riêng của nó.
## 38.33 Truy tìm lại sự hiểu biết
Nếu một ngoại lệ xảy ra bên trong phần hiểu, thì quá trình truy nguyên có thể bao gồm cả chức năng bên ngoài và phần hiểu.```python
def f(xs):
return [10 / x for x in xs]
f([1, 0])
```Việc chia cho số 0 xảy ra bên trong mã hiểu.
Về mặt khái niệm:```text
frame f
calls <listcomp>
division by zero
```Đây là một hiệu ứng có thể nhìn thấy khác của việc hiểu các đối tượng mã.
## 38.34 Khả năng hiểu có thể thay đổi trọn đời
Một biến vòng lặp hiểu tồn tại trong phạm vi hiểu.
Sau khi hoàn thành:```python
def f():
result = [x for x in range(3)]
return "x" in locals()
print(f())
```Điều này trả về:```text
False
```Biến vòng lặp`x`đã không trở thành người địa phương ở`f`.
Bên trong khung hiểu,`x`tồn tại trong khi sự hiểu biết chạy.
## 38.35 Phím tắt đối số biểu thức trình tạo
Một biểu thức trình tạo có thể được chuyển làm đối số duy nhất cho hàm mà không cần thêm dấu ngoặc đơn.```python
total = sum(x * x for x in xs)
```Điều này tương đương với:```python
total = sum((x * x for x in xs))
```Nhưng nếu có nhiều đối số thì bắt buộc phải có dấu ngoặc đơn:```python
result = func((x for x in xs), other)
```Đây là sự tiện lợi ở cấp độ cú pháp. Đối tượng thời gian chạy vẫn là biểu thức trình tạo.
## 38.36 Hiểu biết và tích hợp
Sự hiểu biết thường kết hợp với các phần dựng sẵn.
Ví dụ:```python
sum(x for x in xs)
any(x > 0 for x in xs)
all(x.valid for x in items)
max(score(x) for x in xs)
```Chúng sử dụng các biểu thức của trình tạo và có thể dừng sớm trong một số trường hợp.`any`dừng ở giá trị thực đầu tiên.`all`dừng ở giá trị sai đầu tiên.`sum`tiêu thụ toàn bộ máy phát điện.
Việc chọn biểu thức trình tạo sẽ tránh tạo danh sách trung gian không cần thiết.
## 38.37 Những hiểu lầm phổ biến
| Hiểu lầm | Đúng mẫu |
|---|---|
| Việc hiểu chỉ là viết lại cú pháp trong cùng một phạm vi | Nó thường có đối tượng và phạm vi mã lồng nhau |
| Biến vòng lặp rò rỉ ra phạm vi bên ngoài | Trong Python 3 thì không |
| Biểu thức trình tạo xây dựng một bộ dữ liệu | Nó tạo ra một đối tượng máy phát điện |
| Việc hiểu danh sách luôn tốt hơn | Biểu thức của trình tạo tốt hơn cho việc phát trực tuyến và dừng sớm |
| Sự hiểu biết không thể nắm bắt được các biến bên ngoài | Họ có thể nắm bắt thông qua việc đóng cửa |
| Mỗi lambda trong một cách hiểu sẽ nắm bắt một biến vòng lặp khác nhau | Họ thường chia sẻ cùng một biến hiểu biết ràng buộc |
| Các ngoại lệ xảy ra khi biểu thức trình tạo được tạo | Chúng xảy ra khi nó được tiêu thụ |
| Hiểu chính tả giữ các khóa trùng lặp | Các giá trị sau ghi đè lên các giá trị trước đó |
## 38.38 Chiến lược đọc
Bắt đầu với:```python
def f(xs):
return [x * 2 for x in xs if x > 0]
```Thanh tra:```python
import dis
dis.dis(f)
for const in f.__code__.co_consts:
if hasattr(const, "co_code"):
print(const.co_name)
dis.dis(const)
```Sau đó so sánh với:```python
def g(xs):
return (x * 2 for x in xs if x > 0)
```Theo dõi:```text
outer function bytecode
nested comprehension code object
iteration setup
local loop variable
filter jump
append or yield operation
return value
closure variables
```Sau đó nghiên cứu các cách hiểu về tập hợp, chính tả, lồng nhau và không đồng bộ.
## 38.39 Tóm tắt chương
Phần hiểu là các đơn vị thực thi được biên dịch để xây dựng danh sách, bộ, từ điển hoặc các trình vòng lặp giống như trình tạo. Chúng kết hợp việc lặp lại, lọc, đánh giá biểu thức, liên kết và xây dựng vùng chứa ở dạng biểu thức.
Mô hình cốt lõi là:```text
evaluate outer iterable
↓
create comprehension execution scope
↓
iterate
↓
apply filters
↓
compute element, key-value pair, or yielded value
↓
append, add, store, or yield
↓
return container or generator object
```Khả năng hiểu danh sách, tập hợp và chính tả rất háo hức. Biểu thức của trình tạo là lười biếng. CPython triển khai các cấu trúc này bằng cách sử dụng các đối tượng mã lồng nhau, trạng thái khung, xử lý đóng, các hoạt động mã byte chuyên dụng và truyền bá ngoại lệ thông thường.