List Comprehension trong Python: Viết code ngắn gọn hơn
Bạn đã từng phải viết 3–4 dòng code chỉ để tạo một cái list chưa? Nếu bạn đang học Python, chắc chắn bạn đã từng làm như thế này:
squares = []
for x in range(10):
squares.append(x**2)
print(squares)
# Kết quả: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Code này chạy được, nhưng Python có một cách viết ngắn gọn hơn nhiều — gọi là List Comprehension. Chỉ với một dòng duy nhất, bạn có thể làm điều tương tự:
squares = [x**2 for x in range(10)]
print(squares)
# Kết quả: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Trong bài viết này, bạn sẽ học cú pháp cơ bản của List Comprehension, xem các ví dụ thực tế từ dễ đến khó, và biết khi nào nên — và không nên — dùng nó.
Nếu bạn chưa biết Python là gì, hãy đọc bài Python là gì? Giới thiệu cho người mới bắt đầu trước nhé.
List Comprehension là gì?
List Comprehension (biểu thức danh sách) là một cú pháp đặc trưng của Python, cho phép bạn tạo một list mới từ một iterable (danh sách, range, chuỗi...) chỉ trong một dòng code.
Đây là cách viết Python theo phong cách "Pythonic" — ngắn gọn, rõ ràng và hiệu quả. List Comprehension được giới thiệu từ Python 2.0 và là một trong những tính năng phổ biến nhất của Python hiện đại.
Nói đơn giản, List Comprehension giống như một câu lọc dữ liệu: "Lấy tất cả số chẵn từ 0 đến 20 và bỏ vào một list." Thay vì viết vài dòng, bạn diễn đạt điều đó trong một dòng duy nhất.
Cú pháp cơ bản
Cú pháp của List Comprehension có hai dạng:
# Dạng cơ bản
[biểu_thức for biến in iterable]
# Dạng có điều kiện lọc
[biểu_thức for biến in iterable if điều_kiện]
Giải thích từng thành phần:
- biểu_thức: Giá trị được tính toán và thêm vào list kết quả
- biến: Biến lặp, nhận lần lượt từng giá trị từ iterable
- iterable: Đối tượng có thể lặp: list, tuple, range, string, dict...
- if điều_kiện (tùy chọn): Chỉ lấy các phần tử thỏa mãn điều kiện này
numbers = [x for x in range(5)]
print(numbers)
# Kết quả: [0, 1, 2, 3, 4]
Nếu bạn chưa quen với List trong Python, hãy đọc bài List trong Python: Hướng dẫn đầy đủ cho người mới trước khi tiếp tục.
So sánh với vòng lặp for thông thường
Hãy xem hai cách viết cùng một logic — tạo danh sách bình phương từ 0 đến 9:
Cách 1: Dùng vòng lặp for (truyền thống)
squares = []
for x in range(10):
squares.append(x**2)
print(squares)
# Kết quả: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Cách 2: Dùng List Comprehension
squares = [x**2 for x in range(10)]
print(squares)
# Kết quả: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Kết quả hoàn toàn giống nhau. Nhưng List Comprehension có những ưu điểm:
| Tiêu chí | Vòng lặp for | List Comprehension |
|---|---|---|
| Số dòng code | 3 dòng | 1 dòng |
| Dễ đọc (logic đơn giản) | Bình thường | Cao hơn |
| Tốc độ thực thi | Cơ sở | Nhanh hơn ~1.3–1.5x |
| Dễ debug | Dễ hơn | Khó hơn một chút |
Chưa quen với vòng lặp for? Hãy xem bài Vòng lặp for trong Python: Hướng dẫn từ A đến Z để nắm vững cơ bản trước.
Ví dụ thực tế từ dễ đến khó
Ví dụ 1: Tạo danh sách bình phương (cơ bản)
# Tạo danh sách bình phương từ 0 đến 9
squares = [x**2 for x in range(10)]
print(squares)
# Kết quả: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Ví dụ 2: Lọc số chẵn (có điều kiện if)
# Chỉ lấy số chẵn trong khoảng 0–19
evens = [x for x in range(20) if x % 2 == 0]
print(evens)
# Kết quả: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
x % 2 == 0 là điều kiện lọc: chỉ giữ lại các số có phần dư
khi chia 2 bằng 0 — tức là số chẵn.
Ví dụ 3: Xử lý danh sách chuỗi
# Chuyển tên ngôn ngữ lập trình sang chữ hoa
names = ["python", "javascript", "java"]
upper_names = [name.upper() for name in names]
print(upper_names)
# Kết quả: ['PYTHON', 'JAVASCRIPT', 'JAVA']
Ví dụ 4: List Comprehension lồng nhau (tạo ma trận)
# Tạo ma trận 3x3
matrix = [[i*j for j in range(1, 4)] for i in range(1, 4)]
print(matrix)
# Kết quả: [[1, 2, 3], [2, 4, 6], [3, 6, 9]]
Bonus: Kết hợp if-else trong biểu thức
# Dán nhãn số chẵn/lẻ
labels = ["chẵn" if x % 2 == 0 else "lẻ" for x in range(6)]
print(labels)
# Kết quả: ['chẵn', 'lẻ', 'chẵn', 'lẻ', 'chẵn', 'lẻ']
Dictionary Comprehension và Set Comprehension
Ý tưởng của List Comprehension còn áp dụng được cho dict và set.
Dictionary Comprehension
# Tạo dict: số -> bình phương
squares_dict = {x: x**2 for x in range(1, 6)}
print(squares_dict)
# Kết quả: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
# Đảo ngược key-value của một dict
original = {"a": 1, "b": 2, "c": 3}
reversed_dict = {v: k for k, v in original.items()}
print(reversed_dict)
# Kết quả: {1: 'a', 2: 'b', 3: 'c'}
Set Comprehension
# Tạo set bình phương — tự động loại bỏ trùng lặp
nums = [1, 2, 2, 3, 3, 3, 4]
unique_squares = {x**2 for x in nums}
print(unique_squares)
# Kết quả: {1, 4, 9, 16}
Khi nào nên dùng và khi nào không nên dùng?
Nên dùng List Comprehension khi:
- Logic đơn giản, biểu thức ngắn gọn
- Muốn tạo list mới từ một iterable có sẵn
- Muốn viết code Pythonic, súc tích
Không nên dùng khi:
- Logic phức tạp, nhiều bước xử lý hoặc cần bắt exception
- Comprehension dài hơn 80 ký tự (theo PEP 8)
- Cần debug từng bước một
# Khó đọc — nên viết lại bằng for loop
result = [process(item) for sublist in nested_list for item in sublist if cond1(item) and cond2(item)]
# Dễ đọc hơn với for loop
result = []
for sublist in nested_list:
for item in sublist:
if cond1(item) and cond2(item):
result.append(process(item))
Triết lý Python: "Readability counts" — code dễ đọc quan trọng hơn code ngắn. Đừng lạm dụng List Comprehension chỉ để tiết kiệm dòng.
# Tiết kiệm bộ nhớ hơn khi list có hàng triệu phần tử
squares_gen = (x**2 for x in range(1000000))
Tổng kết
Qua bài viết này, bạn đã học được:
- List Comprehension là gì: Cú pháp Python giúp tạo list trong một dòng code
- Cú pháp cơ bản:
[biểu_thức for biến in iterable]và dạng có điều kiện - So sánh với for loop: Ngắn hơn, nhanh hơn, nhưng chỉ nên dùng khi logic đơn giản
- Dict & Set Comprehension: Áp dụng cùng ý tưởng cho dict và set
- Khi nào không nên dùng: Logic phức tạp thì for loop vẫn tốt hơn
Hãy thử ngay: lấy một đoạn code có vòng lặp for của bạn và thử viết lại bằng List Comprehension. Đó là cách tốt nhất để ghi nhớ cú pháp mới!
Bài tiếp theo bạn nên đọc: