Bài học theo mô-đun (3/4)
biểu thức máy phát điện
Biểu thức trình tạo giống như một cách hiểu danh sách, nhưng với dấu ngoặc đơn thay vì dấu ngoặc vuông. Sự khác biệt rất ấn tượng: nó không tạo danh sách trong bộ nhớ, nó tạo ra các phần tử theo yêu cầu, từng cái một.
gen = (n * n for n in range(1_000_000))
# istantaneo, memoria costante: nessun calcolo ancora fatto
list_comp = [n * n for n in range(1_000_000)]
# alloca 1M di int in memoriaLười biếng (đánh giá lười biếng)
Trình tạo không làm gì cho đến khi ai đó yêu cầu giá trị tiếp theo:
gen = (n * n for n in range(5))
next(gen) # 0 (calcolato adesso)
next(gen) # 1
next(gen) # 4
# ... e così via, fino a StopIterationNó cạn kiệt: sau khi tiêu thụ tất cả các phần tử, nó trống mãi mãi. Để sử dụng lại nó, bạn phải tạo lại nó.
Khi nào nên sử dụng nó
Khi bạn chuyển kết quả cho một hàm tiêu thụ chúng theo trình tự:
total = sum(n * n for n in range(1_000_000))
# nessuna lista intermedia, memoria costantesum, any, all, max, min, "".join(...) đều chấp nhận máy phát điện.
Nếu hàm ngoài chỉ yêu cầu dấu ngoặc đơn gọi, bạn có thể
bỏ qua phần riêng của máy phát điện:
sum((n * n for n in range(10))) # OK
sum(n * n for n in range(10)) # IDENTICO, più leggibileany và all: đoản mạch
any(...) và all(...) ngừng lặp lại ngay khi họ có câu trả lời.
Với một trình tạo, các phần tử sau thậm chí không được tính toán.
nums = [1, 2, 3, 4, 5]
any(n > 3 for n in nums) # True (si ferma a 4)
all(n > 0 for n in nums) # True
all(n > 2 for n in nums) # False (si ferma a 1)Hoa văn: đường ống lười biếng
righe = (linea.strip() for linea in testo.splitlines())
non_vuote = (r for r in righe if r)
prime_dieci = []
for r in non_vuote:
prime_dieci.append(r)
if len(prime_dieci) == 10:
breakKhông có danh sách trung gian, ngay cả trên đầu vào lớn.
Tiêu thụ máy phát điện với tổng, bất kỳ, tất cả
Biểu thức trình tạo hoàn hảo để truyền trực tiếp đến các hàm sử dụng các lần lặp, như sum(), any() hoặc all(). Trong trường hợp này, bạn có thể bỏ qua dấu ngoặc đơn bên ngoài của biểu thức trình tạo, chỉ cần viết:
squares_sum = sum(x**2 for x in range(10))Điều này giữ cho mã của bạn sạch sẽ và tiết kiệm bộ nhớ cao.
Hãy thử nó
Tính tổng bình phương của các số từ 1 đến 100 (bao gồm) bằng cách sử dụng biểu thức tạo bên trong sum(). Gán nó cho `tot`. Đánh giá `tot`.
Hiển thị gợi ý
phạm vi (1, 101) bao gồm 100.
Giải pháp khả dụng sau 3 lần thử
Xem lại bài tập
Cho `words = ['ciao', 'mondo', 'PYTHON', 'java']`, hãy sử dụng bất kỳ() nào với biểu thức trình tạo để kiểm tra xem ÍT NHẤT một từ có phải là chữ hoa hay không (.isupper()). Gán kết quả cho `has_uppercase`. Đánh giá `has_uppercase`.
Hiển thị gợi ý
bất kỳ(p.isupper() cho p trong từ)
Giải pháp khả dụng sau 3 lần thử
Thử thách bổ sung
Use a generator expression passed directly to the `sum()` function to calculate the sum of the squares of all integers from 1 to 100 inclusive. Store the result in `total_sum` and evaluate it.
Hiển thị gợi ý
Viết Total_sum = sum(x**2 cho x trong phạm vi (1, 101)). Dấu ngoặc kép là không cần thiết.
Giải pháp khả dụng sau 3 lần thử