2015-07-05 26 views

Trả lời

33

Trong Python 3.x,

range(0,3) trả về một lớp học của các đối tượng iterable bất biến cho phép bạn duyệt qua họ, nó không tạo ra các danh sách, và họ không lưu trữ tất cả các yếu tố trong phạm vi trong bộ nhớ, thay vì chúng tạo ra các phần tử trên bay (khi bạn đang lặp lại chúng), trong khi list(range(0,3)) tạo danh sách (bằng cách lặp qua tất cả các phần tử và thêm vào danh sách nội bộ).

Ví dụ -

>>> range(0,3) 
range(0, 3) 
>>> list(range(0,3)) 
[0, 1, 2] 

Lý tưởng nhất, nếu bạn chỉ muốn để lặp qua phạm vi của các giá trị, range(0,3) sẽ nhanh hơn (list(range(0,3)) vì sau này có chi phí sản xuất một danh sách trước khi bạn bắt đầu lặp lại trên nó.

Trong Python 2.x, range(0,3) tạo ra một danh sách, thay vào đó chúng tôi cũng có một chức năng xrange() có hành vi tương tự của range() chức năng từ Python 3.x (xrange được đổi tên thành dao động trong Python 3.x)

đối với Python 3.5, Từ documentation -

đối tượng Phạm vi thực hiện collections.abc.Sequence ABC, và cung cấp các tính năng như kiểm tra ngăn chặn, tra cứu chỉ số phần tử, cắt và hỗ trợ cho chỉ số tiêu cực

Vì vậy, bạn có thể làm những việc như -

>>> range(0,10)[5] 
5 
>>> range(0,10)[3:7] 
range(3, 7) 
>>> 5 in range(6,10) 
False 
>>> 7 in range(1,8) 
True 

Và tất cả trong số này là các hoạt động thời gian liên tục, như có thể thấy từ thử nghiệm này -

In [11]: %timeit a = xrange(0,1000000)[1000] 
1000000 loops, best of 3: 342 ns per loop 

In [12]: %timeit a = xrange(0,1000000)[10000] 
1000000 loops, best of 3: 342 ns per loop 

In [13]: %timeit a = xrange(0,1000000)[100000] 
1000000 loops, best of 3: 342 ns per loop 

In [14]: %timeit a = xrange(0,1000000)[999999] 
1000000 loops, best of 3: 342 ns per loop 

In [15]: %timeit a = xrange(0,10000000)[9999999] 
1000000 loops, best of 3: 339 ns per loop 

In [16]: %timeit a = xrange(0,1000000000000)[9999999999] 
1000000 loops, best of 3: 341 ns per loop 
+0

Vì vậy, trong Python 3 là 'phạm vi (x, y)' một cái gì đó giống như một máy phát điện? Chỉ cần một cái gì đó tôi đã tự hỏi bao giờ hết kể từ khi lần đầu tiên tôi nhìn thấy hành vi này ... – Kyrubas

+0

Cố ý cho bây giờ, bởi vì người phiên dịch trực tuyến tôi đã sử dụng để nhận được ví dụ timeit là Python 2.7, vì vậy tôi sử dụng xrange thay vì phạm vi. Nhưng nó không nên quan trọng bởi vì phạm vi Python 3 là Python 2.x's xrange() –

+0

Ok tôi đã tìm ra nó giống như vậy. Chỉ muốn chắc chắn rằng nó là cố ý. – Scott

12

Tùy thuộc vào phiên bản Python bạn đang sử dụng.

Trong Python 2.x, range() trả về danh sách, vì vậy chúng tương đương nhau.

Trong Python 3.x, trả về loại chuỗi không thay đổi, bạn cần list(range(0,2)) để nhận danh sách.

+4

Thực ra 'dải ô' không trả về một trình tạo, một đối tượng bất biến của nó. Thử làm 'next (range (0,5))'. Bạn sẽ hiểu. –

+0

@AnandSKumar Đã sửa ngay bây giờ. –

1

Trong python3.x, phạm vi có riêng của mình loại

>>> range(1) 
range(0, 1) 
>>> type(range(1)) 
<class 'range'> 

Vì vậy, nếu bạn muốn sử dụng dải() trong vòng lặp for, tiền phạt của nó. Tuy nhiên, bạn không thể sử dụng nó purely làm đối tượng danh sách. Bạn cần phải chuyển đổi nó thành danh sách để làm điều đó.

python2 Ví dụ:

>>> L = range(10) 
>>> L[::-1] 
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0] 

Python3 Ví dụ:

>>> L = range(10) 
>>> L[::-1] 
range(9, -1, -1) 
+1

Bạn có thể cắt một loạt - '>>> range (0,3) [1: 3] phạm vi (1, 3)' –

+0

Như @AnandSKumar chỉ ra trong câu trả lời của mình, python3 'phạm vi() 'là một loại chuỗi và có các hoạt động tương tự như danh sách và các bộ (trừ concat và lặp lại) https://docs.python.org/3/library/stdtypes.html#sequence-types-list-tuple-range – Scott

+0

@Anand, bạn là đúng về việc cắt mà nó hoạt động trên đó. Tôi đã cập nhật câu trả lời của tôi về những gì tôi có ý nghĩa. Cảm ơn! –

2

Cả hai lệnh trở lại danh sách trong Python2.x. Nhưng trong phạm vi Python3.x là một chuỗi bất biến và không trả về danh sách. Nó được sử dụng cho quảng cáo lặp đi lặp lại vòng

1

Về cơ bản, sự khác biệt là range(0, 2) là một chức năng máy phát điện và list(range(0, 2)) là một danh sách thực tế.

Chức năng máy phát được sử dụng trong các vòng lặp. Ví dụ, một chức năng máy phát của một tập tin sẽ đọc một dòng tệp rất lớn theo từng dòng.

def gen(): 
    for line in open("hugefile.csv", "r"): 
     yield line #Gives back the line every time it is read, but forgets that line after 

for line in gen(): 
    print(line) 

Điều này sẽ in mọi dòng mà không làm quá tải RAM của máy tính vì bạn chỉ đọc từng cái một trong cả hai chức năng. Tuy nhiên, nếu chúng tôi làm điều gì đó như

def readEntireFile(): 
    return [line for line in open("hugefile.csv", "r")] #Python has lazy ways of making lists, this is the same as returning a list with all the lines in the file 

for line in readEntireFile(): 
    print(line) 

Phần thứ hai trông giống nhau, nhưng không phải như vậy. Ban đầu, chúng tôi đã lặp lại tất cả các dòng trong tệp và chuyển sang dòng tiếp theo khi chúng tôi đã thực hiện xong. Ở đây, Python có một danh sách tất cả các dòng: /, hãy tưởng tượng làm điều đó với một tập tin 10GB! Mã của bạn sẽ bị lỗi.

Bây giờ, chúng ta hãy quay trở lại phạm vi() và danh sách (range())

Làm for x in range(0, 6): làm cho chúng ta đi đến số tiếp theo trong phạm vi và hoàn toàn quên về (Vít ngữ pháp) trước.

Tuy nhiên, làm for x in list(range(0, 6)): giữ toàn bộ danh sách các số trong bộ nhớ và cũng giống như làm

numlist = [x for x in range(6)] 
for x in numlist: 
    print(x) 

Khi bạn cần toàn bộ danh sách các dữ liệu trong mã của bạn, sử dụng phương pháp danh sách. Tuy nhiên, khi bạn chỉ cần một phần dữ liệu tại một thời điểm (ví dụ dễ nhất, sao chép một tệp theo khối), hãy sử dụng chức năng của trình tạo để tiết kiệm dung lượng. Bạn có thể sao chép mỗi 1 triệu dòng của một tệp chỉ bằng 54 mb (giả sử bạn không có đường dài điên rồ). Tuy nhiên, nếu chúng ta có một tệp 2kb nhỏ, chúng ta chỉ có thể sao chép thứ đó mà không có máy phát. Nó không có giá trị thời gian và chậm hơn trong trường hợp này.

Các vấn đề liên quan