List comprehension trong Python: cú pháp, ví dụ và khi nào nên tránh
Tìm hiểu list comprehension trong Python từng bước: tạo, lọc và biến đổi danh sách chỉ trong một dòng, xem thời gian đo thực tế so với vòng lặp và biết khi nào vòng lặp for dễ đọc hơn.
- Mẫu chung là
[biểu thức for phần tử in iterable if điều kiện]. ifđơn giản ở cuối dùng để lọc;if-elseở đầu dùng để chọn giữa hai giá trị.- Trong bài đo của chúng tôi, comprehension nhanh hơn vòng lặp dùng
appendkhoảng 37%. - Dùng generator expression cho dữ liệu rất lớn, và dùng vòng lặp thường khi logic cần nhiều bước rõ ràng.
List comprehension trong Python tạo danh sách mới từ bất kỳ iterable nào chỉ trong một dòng dễ đọc. Thay vì tạo danh sách rỗng, lặp qua rồi gọi append, bạn mô tả kết quả mình muốn.
Hướng dẫn này đi từ mẫu cơ bản đến bộ lọc, vòng lặp lồng nhau và thời gian do chính chúng tôi đo. Nếu bạn mới học Python, hãy bắt đầu với hướng dẫn Python cho người mới (tiếng Anh) và giữ môi trường gọn gàng với hướng dẫn môi trường ảo (tiếng Anh).
Cú pháp list comprehension trong Python
Hãy đọc từ trái sang phải: biểu thức cho biết mỗi phần tử mới trông thế nào, phần for cho biết các phần tử đến từ đâu.
squares = [x * x for x in range(6)]
print(squares) # [0, 1, 4, 9, 16, 25]
names = [" Hi ", " QA "]
clean = [n.strip().lower() for n in names]
print(clean) # ['hi', 'qa']
Cùng kết quả đó nếu dùng vòng lặp sẽ cần thêm ba dòng. Sự gọn gàng đó chính là mục đích, miễn là dòng lệnh vẫn dễ đọc.
Lọc phần tử bằng điều kiện
Thêm if sau vòng lặp để chỉ giữ lại những phần tử thỏa điều kiện.
evens = [x for x in range(10) if x % 2 == 0]
print(evens) # [0, 2, 4, 6, 8]
List comprehension trong Python với if-else
Khi bạn muốn có một giá trị cho mọi phần tử, hãy đặt if-else trước for. Đây là chỗ người mới hay sai nhất, vì else đặt ở cuối là lỗi cú pháp.
labels = ["even" if x % 2 == 0 else "odd" for x in range(4)]
print(labels) # ['even', 'odd', 'even', 'odd']
Quy tắc nhanh: if ở cuối loại bỏ phần tử, if-else ở đầu thay đổi phần tử. Với if-else, độ dài danh sách không đổi.
Vòng lặp lồng nhau và làm phẳng
Nhiều mệnh đề for được đọc theo cùng thứ tự với các vòng lặp lồng nhau. Dùng chúng để làm phẳng danh sách các danh sách hoặc ghép cặp.
matrix = [[1, 2, 3], [4, 5, 6]]
flat = [n for row in matrix for n in row]
print(flat) # [1, 2, 3, 4, 5, 6]
pairs = [(x, y) for x in range(1, 3) for y in "ab"]
print(pairs) # [(1, 'a'), (1, 'b'), (2, 'a'), (2, 'b')]
Để chuyển vị ma trận, hãy lồng một comprehension vào trong comprehension khác: [[r[i] for r in matrix] for i in range(3)] cho kết quả [[1, 4], [2, 5], [3, 6]]. Hai cấp là giới hạn thực tế trước khi khả năng đọc giảm sút.
Dạng dictionary, set và generator
Đổi dấu ngoặc là cùng ý tưởng đó tạo ra các kiểu dữ liệu khác.
lengths = {w: len(w) for w in ["pip", "venv", "uv"]} # {'pip': 3, 'venv': 4, 'uv': 2}
unique = {len(w) for w in ["pip", "venv", "uv", "git"]} # {2, 3, 4}
total = sum(x * x for x in range(1_000_000)) # generator, no list
So sánh chính các kiểu dữ liệu trong hướng dẫn của chúng tôi về list, tuple, set và dictionary (tiếng Anh).
Tốc độ và bộ nhớ: những gì chúng tôi đo được
Chúng tôi đo từng cách trên Python 3.13.6 với 100.000 số nguyên, lấy kết quả tốt nhất trong năm lần chạy. Số của bạn sẽ khác, nhưng thứ tự thì ổn định.
| Tác vụ | Thời gian |
|---|---|
Vòng lặp dùng append (nhân đôi mỗi phần tử) | 5,18 ms |
| List comprehension (nhân đôi mỗi phần tử) | 3,25 ms |
list(map(lambda ...)) | 6,50 ms |
| Lọc số chẵn bằng vòng lặp | 3,62 ms |
| Lọc số chẵn bằng comprehension | 3,43 ms |
Comprehension vượt rõ rệt vòng lặp append, nhưng khoảng cách thu hẹp khi phần lớn thời gian dành cho điều kiện. Về bộ nhớ, danh sách một triệu số nguyên đã nhân đôi chiếm khoảng 8,4 MB, trong khi đối tượng generator tương đương chỉ 200 byte vì nó tạo từng giá trị một.
Khi nào không nên dùng list comprehension
- Bạn chỉ cần tác dụng phụ như in hoặc lưu. Hãy dùng vòng lặp thường; comprehension sẽ tạo ra một danh sách vô ích.
- Logic có nhiều bước. Nếu cần biến thứ hai hoặc
try, hãy viết vòng lặp hoặc một hàm nhỏ. - Dữ liệu rất lớn. Dùng generator expression để Python không giữ toàn bộ danh sách trong bộ nhớ.
- Cần hơn hai mệnh đề
for. Hãy chia thành các bước có tên cho người đọc sau.
Lời kết
Hãy dùng list comprehension trong Python khi một dòng ngắn nói đúng điều bạn muốn, và dùng vòng lặp khi không. Bắt đầu với mẫu cơ bản, thêm một bộ lọc, rồi luyện dạng if-else cho đến khi thứ tự trở nên tự nhiên.
Câu hỏi thường gặp
List comprehension trong Python là gì?
Đó là cách ngắn gọn để tạo danh sách bằng cách áp dụng một biểu thức cho từng phần tử của iterable, kèm điều kiện tùy chọn để lọc.
Dùng if-else trong list comprehension như thế nào?
Đặt biểu thức điều kiện trước mệnh đề for, ví dụ ["even" if x % 2 == 0 else "odd" for x in nums]. Bộ lọc đơn giản chỉ dùng một if sau vòng lặp.
List comprehension có nhanh hơn vòng lặp for không?
Thường là có. Trong bài đo với 100.000 phần tử, nó nhanh hơn vòng lặp dùng append khoảng 37%, nhưng khả năng đọc nên được cân nhắc trước.
List comprehension khác generator expression thế nào?
List comprehension tạo toàn bộ danh sách trong bộ nhớ cùng lúc. Generator expression dùng dấu ngoặc tròn và tạo từng giá trị một, giúp tiết kiệm bộ nhớ với dữ liệu lớn.
Có thể lồng các list comprehension không?
Có, để làm phẳng hoặc chuyển vị ma trận. Hãy giữ ở hai cấp và chuyển sang vòng lặp nếu khó đọc.
Tiếp tục học (bài viết tiếng Anh)
Cần hỗ trợ về kiểm thử, WordPress hoặc SEO?
Chúng tôi giúp các nhóm phát hành phần mềm tốt hơn và phát triển website. Hãy cho chúng tôi biết bạn đang làm gì, chúng tôi sẽ gợi ý bước tiếp theo rõ ràng.
Thêm hướng dẫn về thử nghiệm, AI và phát triển hiện đại
Bạn thích bài viết này? Chọn một chủ đề và chuyển ngay sang phần hướng dẫn mới nhất của chúng tôi.
Giải thích về ảo giác AI: Tại sao các mô hình ngôn ngữ lại tạo nên mọi thứ và cách giảm thiểu nó
Ảo giác AI đã giải thích: chúng là gì, tại sao mô hình ngôn ngữ tạo ra chúng, các loại phổ biến, cách giảm thiểu chúng bằng cách căn cứ và nhắc nhở …
Đọc bài viết →DevOpsGiải thích về các biến môi trường: Tệp .env, bí mật và cấu hình được thực hiện đúng
Các biến môi trường được giải thích bằng các ví dụ Python mà chúng tôi đã chạy: đọc và thiết lập chúng, tại sao mọi giá trị đều là một chuỗi, tệp .e…
Đọc bài viết →Phát triển phần mềmGiải thích về giới hạn tỷ lệ API: Thuật toán, tiêu đề và xử lý lỗi 429
Giới hạn tốc độ API được giải thích bằng mô phỏng mà chúng tôi đã chạy: nhóm mã thông báo, cửa sổ cố định, cửa sổ trượt, 429 phản hồi, tiêu đề giới …
Đọc bài viết →Tự động hóa kiểm thửChế giễu bằng Python: unittest.mock, patch và những sai lầm khiến bài kiểm tra nói dối
Mô phỏng bằng Python với unittest.mock, đã được thử nghiệm: Mock và return_value, side_effect, vá lỗi nơi sử dụng tên, thông số kỹ thuật và thông số…
Đọc bài viết →Kiểm thử phần mềmGiải thích về phạm vi bảo hiểm của mã: Phạm vi tuyến so với chi nhánh và ý nghĩa thực sự 100%
Phạm vi bảo hiểm mã được giải thích bằng cách chạy phạm vi bảo hiểm thực tế: phạm vi bảo hiểm dòng, chi nhánh và điều kiện, đọc báo cáo, lý do tại s…
Đọc bài viết →Cơ sở dữ liệu & SQLDELETE vs TRUNCATE vs DROP trong SQL: Sự khác biệt, khôi phục và thời điểm sử dụng mỗi loại
DELETE vs TRUNCATE vs DROP được giải thích bằng SQL đã được thử nghiệm: mỗi loại loại bỏ, khôi phục, kích hoạt, đặt lại danh tính, tốc độ và Postgre…
Đọc bài viết →Cơ sở dữ liệu & SQLGiải thích về Chế độ xem SQL: Tạo, sử dụng và tránh những cạm bẫy, kèm theo ví dụ
Chế độ xem SQL được giải thích bằng các truy vấn chúng tôi đã chạy: tạo chế độ xem, kết quả trực tiếp, ẩn cột, hiệu suất, chế độ xem có thể cập nhật…
Đọc bài viết →Phát triển phần mềmGiao diện TypeScript so với loại: Sự khác biệt thực sự, được thử nghiệm bằng trình biên dịch
Giao diện TypeScript so với loại, được kiểm tra bằng trình biên dịch thực: cả hai có thể làm gì, chỉ một người có thể làm gì, hợp nhất khai báo, mở …
Đọc bài viết →Phát triển phần mềmGiải thích về Python *args và **kwargs: Hàm linh hoạt với ví dụ rõ ràng
Python *args và **kwargs được giải thích bằng mã chúng tôi đã chạy: đóng gói và giải nén, thứ tự tham số, đối số chỉ từ khóa và chỉ vị trí, trình tr…
Đọc bài viết →Phát triển phần mềmHàm Lambda của Python: Cú pháp, cách sử dụng thực tế và khi nào không nên sử dụng chúng
Các hàm lambda của Python được giải thích bằng mã chúng tôi đã chạy: cú pháp, sắp xếp bằng khóa, bản đồ và bộ lọc, các phần đóng, bẫy liên kết muộn …
Đọc bài viết →Trí tuệ nhân tạoĐại lý AI là gì? Cách chúng hoạt động, với vòng lặp tác nhân đơn giản, bạn có thể chạy
Tác nhân AI là gì? Hướng dẫn đơn giản về vòng lặp tác nhân, công cụ, bộ nhớ và lan can, với một vòng lặp Python nhỏ mà chúng tôi đã chạy, những rủi …
Đọc bài viết →DevOpsGiám sát và Khả năng quan sát: Sự khác biệt thực sự, với nhật ký, số liệu và dấu vết
Giải thích về giám sát và khả năng quan sát: lỗi đã biết và chưa biết, nhật ký, số liệu và dấu vết, hướng dẫn về sự cố thanh toán, tín hiệu vàng, Op…
Đọc bài viết →DevOpsDocker Volumes vs Bind Mounts: Duy trì dữ liệu vùng chứa đúng cách
Giải thích về khối lượng Docker và liên kết gắn kết: tại sao dữ liệu vùng chứa biến mất, khối lượng được đặt tên, liên kết gắn kết, tmpfs, ví dụ về …
Đọc bài viết →Tự động hóa kiểm thửTDD vs BDD: Key Differences, One Feature Built Both Ways and When to Use Each
TDD và BDD được giải thích bằng một tính năng giảm giá được xây dựng theo cả hai cách: tái cấu trúc màu đỏ-xanh với mã chúng tôi đã chạy, kịch bản C…
Đọc bài viết →Phát triển phần mềmGit merge vs rebase: khác biệt, ví dụ và khi nào dùng cái nào
Git merge vs rebase được giải thích bằng đầu ra log thực tế, bảng so sánh, quy tắc vàng của rebase và quy trình làm việc nhóm an toàn.
Đọc bài viết →Phát triển phần mềmList comprehension trong Python: cú pháp, ví dụ và khi nào nên tránh
List comprehension trong Python: cú pháp, lọc dữ liệu, if-else, vòng lặp lồng nhau, thời gian đo thực tế và khi nào vòng lặp for thông thường tốt hơn.
Đọc bài viết →Cơ sở dữ liệu & SQLGiải thích SQL JOIN kèm ví dụ (Inner, Left, Right, Full)
Hiểu SQL JOIN từng bước với bảng và truy vấn mẫu: INNER, LEFT, RIGHT, FULL, CROSS và SELF, cùng lỗi thường gặp và mẹo hiệu năng.
Đọc bài viết →