List comprehension trong Python: cú pháp, ví dụ và khi nào nên tránh

  1. Trang chủ
  2. Blog
  3. Phát triển phần mềm
Phát triển phần mềm

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.

7 phút đọc
List comprehension trong Python: cú pháp, ví dụ và khi nào nên tránh
Điểm chính
  • 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 append khoả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ặp3,62 ms
Lọc số chẵn bằng comprehension3,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)

Làm việc với Stack Quora

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.

Tiếp tục đọc

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.

Trí tuệ nhân tạo

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 →
DevOps

Giả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ềm

Giả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ềm

Giả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 & SQL

DELETE 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 & SQL

Giả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ềm

Giao 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ềm

Giả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ềm

Hà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 →
DevOps

Giá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 →
DevOps

Docker 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ềm

Git 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ềm

List 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 & SQL

Giả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 →