Menu

Hàm range() trong Python: start, stop, step và đếm ngược

Cách range() hoạt động trong Python: start, stop, step, khoảng số âm và vì sao range là lazy chứ không tạo ra cả một list.

Trang này có trình soạn thảo chạy trực tiếp. Sửa, chạy và xem đầu ra ngay lập tức.

Công cụ tạo ra các con số

range() chỉ làm đúng một việc: tạo ra một dãy số nguyên. Nó là người bạn đồng hành quen thuộc của vòng lặp for khi bạn cần lặp một số lần nhất định hoặc đi qua một khoảng số.

Dạng đơn giản nhất nhận một đối số, giá trị stop:

Đầu ra:

0
1
2
3
4

Hai chi tiết hay làm người mới vấp:

  1. Đếm bắt đầu từ 0. range(5) cho bạn năm số, bắt đầu từ 0.
  2. Giá trị stop không được tính. range(5) dừng trước 5, không gồm chính số 5.

Những quy tắc này nhất quán trong slicing, chỉ số và range của Python. Khi đã thấm "stop không được tính", bạn sẽ không còn vấp nữa.

Ba dạng

range() nhận một, hai hoặc ba đối số:

Step là độ lớn của mỗi bước nhảy. range(0, 20, 4) cho ra cứ mỗi số thứ tư. Hãy nhớ điều này khi cần "cách một phần tử lấy một" hay "mỗi mẫu thứ mười".

Đếm ngược

Step có thể là số âm, cho phép bạn đếm ngược:

Một lần nữa, stop không được tính: range(10, 0, -1) dừng trước 0, chứ không phải tại 0. Để có cả 0, hãy đặt stop là -1:

range là lazy

Trong Python 3, range() không tạo một list số trong bộ nhớ. Nó trả về một đối tượng range gọn nhẹ, sinh từng số một khi được yêu cầu. Đó là lý do bạn có thể viết:

Một "range" một tỷ số gần như không tốn bộ nhớ. Các số được sinh ra khi vòng lặp cần đến.

Nếu bạn thật sự cần một list các số, vì muốn sửa, sắp xếp hay truy cập theo chỉ số vượt ngoài mức cơ bản, hãy chuyển đổi rõ ràng:

Phần lớn thời gian, bạn không cần list. for i in range(...) dùng trực tiếp được.

Những mẫu thường gặp

Vài công thức bạn sẽ dùng liên tục:

Làm việc gì đó n lần.

_ là một quy ước nghĩa là "tôi không quan tâm đến giá trị này". Python không bắt buộc, nhưng người đọc nào cũng hiểu ý định.

Truy cập phần tử theo chỉ số.

Nên ưu tiên enumerate() hơn range(len(...)), nhưng khi bạn chỉ cần đúng chỉ số:

Dù vậy, phần lớn thời gian enumerate(items) gọn hơn.

Lặp qua cách một phần tử.

Đoạn này in ra a, c, e. Tuy nhiên với việc cắt đơn giản, cú pháp slicing còn trực tiếp hơn: items[::2].

Tạo nhanh một list số.

Đó là một list comprehension, sẽ được nói đến sau, nhưng chính range cung cấp các con số.

Những gì range() không làm được

Hai điểm cần lưu ý:

  1. range chỉ tạo ra số nguyên. Nếu bạn cần bước nhảy số thực (như từ 0.0 đến 1.0 với bước 0.1), hãy dùng numpy.arange hoặc một vòng lặp với bộ đếm của riêng bạn.
  2. range không dùng với iterable bất kỳ. Nó chỉ dành cho số nguyên. Nếu bạn đang định "range" qua một list, có lẽ thứ bạn cần là enumerate hoặc chính list đó.

Kết hợp lại

Một ví dụ nhỏ dùng nhiều biến thể cùng lúc:

Hai vòng lặp lồng nhau chạy bằng range, tạo ra một bảng. Để ý rằng cả hai vòng đều bắt đầu từ 1, range(1, 6), vì ta muốn nhãn từ 1 đến 5.

Chuyển sang các kiểu tập hợp

Bạn đã thấy điều kiện, cả hai loại vòng lặp và range. Như vậy là đủ luồng điều khiển để làm việc với mọi tập hợp. Chương tiếp theo: chính các kiểu tập hợp, gồm list, tuple, set và dictionary.

Câu hỏi thường gặp

Hàm range() làm gì trong Python?

range() tạo ra một dãy số nguyên. range(n) cho các số từ 0 đến n-1. range(start, stop) cho các số nguyên từ start đến trước stop (không gồm stop). range(start, stop, step) cho phép bạn chọn bước nhảy, kể cả bước âm để đếm ngược.

range() có tạo ra list không?

Không. Trong Python 3, range() trả về một đối tượng range gọn nhẹ, sinh số khi cần. Vì thế range(10**9) chạy tức thì: nó không thực sự cấp phát một tỷ số nguyên. Hãy bọc nó trong list(...) nếu bạn thật sự cần một list.

Làm sao để đếm ngược bằng range() trong Python?

Dùng step âm: range(10, 0, -1) đếm 10, 9, 8, ..., 1. Nhớ rằng giá trị stop luôn không được tính, nên muốn có cả 0 thì bạn cần range(10, -1, -1).

Hình minh họa các ngôn ngữ lập trình của Coddy

Học lập trình cùng Coddy

Bắt đầu