Bài 3.22. List comprehension - cú pháp đặc trưng của Python

Bài 3.22. List comprehension - cú pháp đặc trưng của Python
Chào mừng bạn đến với một trong những tính năng thanh lịch và mạnh mẽ nhất của Python: List Comprehension. Đây là một cách cực kỳ Pythonic (mang đậm phong cách Python) để tạo ra các danh sách (list) một cách ngắn gọn và dễ đọc hơn so với việc sử dụng các vòng lặp for
truyền thống kết hợp với phương thức .append()
.
Nếu bạn muốn viết code Python hiệu quả và dễ hiểu, nắm vững list comprehension là một kỹ năng không thể thiếu. Hãy cùng đi sâu vào cú pháp và các ứng dụng tuyệt vời của nó!
Cú Pháp Cơ Bản
Cú pháp đơn giản nhất của list comprehension có dạng:
new_list = [expression for item in iterable]
Hãy phân tích từng thành phần:
expression
: Biểu thức được áp dụng cho mỗiitem
. Kết quả của biểu thức này sẽ là phần tử trong danh sách mới.item
: Biến đại diện cho từng phần tử trongiterable
.iterable
: Bất kỳ đối tượng nào có thể lặp qua (ví dụ: list, tuple, string, range,...).
Ví dụ 1: Tạo danh sách các số bình phương
Giả sử bạn muốn tạo một danh sách chứa bình phương của các số từ 0 đến 9.
Cách truyền thống dùng for
loop:
squares = [] # Khởi tạo danh sách rỗng
for x in range(10): # Lặp qua các số từ 0 đến 9
squares.append(x**2) # Tính bình phương và thêm vào danh sách
print(squares)
# Output: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Cách dùng List Comprehension:
squares_comp = [x**2 for x in range(10)]
print(squares_comp)
# Output: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Giải thích:
x**2
: Đây làexpression
. Với mỗix
, chúng ta tính bình phương của nó.for x
: Đây làitem
.x
lần lượt nhận các giá trị từiterable
.in range(10)
: Đây làiterable
, cung cấp các số từ 0 đến 9.
Bạn thấy đấy, list comprehension giúp viết code ngắn gọn và dễ đọc hơn rất nhiều!
Thêm Điều Kiện Lọc (Filtering)
List comprehension còn cho phép bạn thêm một điều kiện if
để lọc các phần tử từ iterable
trước khi áp dụng expression
.
Cú pháp:
new_list = [expression for item in iterable if condition]
condition
: Biểu thức điều kiện. Chỉ nhữngitem
nào làm chocondition
trả vềTrue
mới được xử lý bởiexpression
.
Ví dụ 2: Lấy các số chẵn từ một danh sách
Cách truyền thống dùng for
loop và if
:
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_numbers = []
for num in numbers:
if num % 2 == 0: # Kiểm tra xem số có chẵn không
even_numbers.append(num)
print(even_numbers)
# Output: [2, 4, 6, 8, 10]
Cách dùng List Comprehension với if
:
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_numbers_comp = [num for num in numbers if num % 2 == 0]
print(even_numbers_comp)
# Output: [2, 4, 6, 8, 10]
Giải thích:
num
:expression
ở đây chỉ đơn giản là lấy chính phần tửnum
.for num in numbers
: Lặp qua từngnum
trongnumbers
.if num % 2 == 0
:condition
. Chỉ nhữngnum
nào chia hết cho 2 (là số chẵn) mới được đưa vào danh sách mới.
Ví dụ 3: Lấy các từ có độ dài lớn hơn 5
words = ["apple", "banana", "kiwi", "strawberry", "orange", "grape"]
long_words = [word.upper() for word in words if len(word) > 5] # Đồng thời chuyển thành chữ hoa
print(long_words)
# Output: ['BANANA', 'STRAWBERRY', 'ORANGE']
Giải thích:
word.upper()
:expression
. Lấy từword
và chuyển thành chữ hoa.for word in words
: Lặp qua từngword
trong danh sáchwords
.if len(word) > 5
:condition
. Chỉ nhữngword
có độ dài lớn hơn 5 mới được chọn và xử lý bởiexpression
.
Sử Dụng Biểu Thức Điều Kiện (Conditional Expression) trong expression
Đôi khi, bạn muốn áp dụng các expression
khác nhau dựa trên một điều kiện cho mỗi item
. Bạn có thể sử dụng biểu thức điều kiện (còn gọi là toán tử ba ngôi - ternary operator) ngay trong phần expression
.
Cú pháp của biểu thức điều kiện: value_if_true if condition else value_if_false
Kết hợp với list comprehension:
new_list = [value_if_true if condition else value_if_false for item in iterable]
Quan trọng: Đừng nhầm lẫn điều này với mệnh đề if
lọc ở phần trước. Mệnh đề if
lọc đặt ở cuối và quyết định xem item
có được xử lý hay không. Biểu thức điều kiện if...else
đặt ở đầu (trong expression
) và quyết định kết quả của expression
cho mỗi item
.
Ví dụ 4: Phân loại số chẵn/lẻ
numbers = range(10) # Các số từ 0 đến 9
parity = ["Even" if x % 2 == 0 else "Odd" for x in numbers]
print(parity)
# Output: ['Even', 'Odd', 'Even', 'Odd', 'Even', 'Odd', 'Even', 'Odd', 'Even', 'Odd']
Giải thích:
"Even" if x % 2 == 0 else "Odd"
: Đây làexpression
sử dụng biểu thức điều kiện. Nếux
chia hết cho 2, kết quả là chuỗi"Even"
, ngược lại là"Odd"
.for x in numbers
: Lặp qua từngx
trongrange(10)
.
So sánh với cách dùng for
loop:
numbers = range(10)
parity_loop = []
for x in numbers:
if x % 2 == 0:
parity_loop.append("Even")
else:
parity_loop.append("Odd")
print(parity_loop)
# Output: ['Even', 'Odd', 'Even', 'Odd', 'Even', 'Odd', 'Even', 'Odd', 'Even', 'Odd']
List comprehension một lần nữa thể hiện sự ngắn gọn vượt trội.
List Comprehension Lồng Nhau (Nested List Comprehensions)
Bạn có thể sử dụng list comprehension để thay thế cho các vòng lặp for
lồng nhau. Điều này đặc biệt hữu ích khi làm việc với các cấu trúc dữ liệu đa chiều như ma trận (danh sách của các danh sách).
Cú pháp:
new_list = [expression for outer_item in outer_iterable for inner_item in inner_iterable]
Thứ tự for
rất quan trọng: Thứ tự các mệnh đề for
trong list comprehension lồng nhau tương ứng với thứ tự các vòng lặp for
từ ngoài vào trong.
Ví dụ 5: Làm phẳng (flatten) một danh sách 2 chiều
Giả sử bạn có một ma trận và muốn tạo một danh sách chứa tất cả các phần tử của nó.
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
Cách dùng vòng lặp for
lồng nhau:
flat_list_loop = []
for row in matrix: # Vòng lặp ngoài
for num in row: # Vòng lặp trong
flat_list_loop.append(num)
print(flat_list_loop)
# Output: [1, 2, 3, 4, 5, 6, 7, 8, 9]
Cách dùng Nested List Comprehension:
flat_list_comp = [num for row in matrix for num in row]
print(flat_list_comp)
# Output: [1, 2, 3, 4, 5, 6, 7, 8, 9]
Giải thích:
num
:expression
. Chúng ta chỉ đơn giản lấy phần tửnum
.for row in matrix
: Vòng lặp ngoài, lặp qua từngrow
(danh sách con) trongmatrix
.for num in row
: Vòng lặp trong, lặp qua từngnum
trongrow
hiện tại.
Ví dụ 6: Tạo một ma trận chuyển vị
matrix = [
[1, 2, 3],
[4, 5, 6]
]
# Kích thước: 2 hàng, 3 cột
# Muốn tạo ma trận chuyển vị: 3 hàng, 2 cột
# Dùng list comprehension lồng nhau
transpose_comp = [[row[i] for row in matrix] for i in range(len(matrix[0]))]
print(transpose_comp)
# Output: [[1, 4], [2, 5], [3, 6]]
Giải thích:
- Vòng lặp ngoài
for i in range(len(matrix[0]))
: Lặp qua các chỉ số cột của ma trận gốc (0, 1, 2). Mỗi giá trịi
sẽ tạo ra một hàng mới trong ma trận chuyển vị. - Vòng lặp trong (comprehension bên trong)
[row[i] for row in matrix]
: Đối với mỗi chỉ số cộti
, nó lặp qua tất cả cácrow
của ma trận gốc và lấy phần tử tại cộti
(row[i]
). Kết quả là một danh sách chứa các phần tử của cộti
trong ma trận gốc, đây chính là hàngi
của ma trận chuyển vị.
Lưu ý về Nested List Comprehensions: Mặc dù mạnh mẽ, list comprehension lồng nhau quá phức tạp có thể trở nên khó đọc. Nếu bạn có nhiều hơn hai vòng lặp lồng nhau hoặc logic phức tạp, việc sử dụng các vòng lặp for
truyền thống có thể giúp code rõ ràng hơn. Hãy cân nhắc giữa sự ngắn gọn và tính dễ hiểu.
Ưu điểm và Khi nào nên sử dụng
- Ngắn gọn và Súc tích: Giảm đáng kể số dòng code so với vòng lặp
for
và.append()
. - Dễ đọc (thường là vậy): Đối với các tác vụ tạo danh sách đơn giản và phổ biến, list comprehension thường dễ đọc và hiểu ý định hơn.
- Hiệu suất: Trong nhiều trường hợp, list comprehension có thể nhanh hơn một chút so với việc sử dụng
for
loop và.append()
do một số tối ưu hóa nội bộ của Python.
Nên sử dụng list comprehension khi:
- Bạn muốn tạo một danh sách mới từ một iterable có sẵn.
- Logic để tạo từng phần tử là tương đối đơn giản.
- Bạn cần lọc các phần tử từ iterable dựa trên một điều kiện.
- Bạn muốn áp dụng một biểu thức đơn giản cho mỗi phần tử được chọn.
Khi nào không nên (hoặc cân nhắc kỹ):
- Khi logic quá phức tạp, làm cho list comprehension trở nên dài dòng và khó đọc.
- Khi bạn cần thực hiện các tác vụ có tác dụng phụ (side effects) bên trong vòng lặp (ví dụ: in ra màn hình, sửa đổi đối tượng khác ngoài danh sách đang tạo). List comprehension chủ yếu dùng để tạo giá trị, không phải để thực hiện hành động.
- Khi bạn làm việc với các cấu trúc lồng nhau quá sâu (nested loops).
List comprehension là một công cụ tuyệt vời trong bộ công cụ của lập trình viên Python. Bằng cách luyện tập và sử dụng chúng một cách hợp lý, bạn có thể viết code Python hiệu quả, ngắn gọn và dễ đọc hơn đáng kể.
Comments