Câu trả lời:
Trong Python 2.x:
range
tạo một danh sách, vì vậy nếu bạn làm range(1, 10000000)
nó sẽ tạo một danh sách trong bộ nhớ với 9999999
các phần tử.
xrange
là một đối tượng trình tự đánh giá một cách lười biếng.
Trong Python 3, range
tương đương với python xrange
, và để có được danh sách, bạn phải sử dụng list(range(...))
.
xrange(x).__iter__()
là một máy phát điện.
i
được đánh giá theo yêu cầu thay vì khởi tạo.
phạm vi tạo một danh sách, vì vậy nếu bạn làm
range(1, 10000000)
nó sẽ tạo một danh sách trong bộ nhớ với9999999
các phần tử.
xrange
là một trình tạo, vì vậy nólà một đối tượng trình tựđượcđánh giá một cách lười biếng.
Điều này đúng, nhưng trong Python 3, .range()
sẽ được Python 2 triển khai .xrange()
. Nếu bạn cần thực sự tạo danh sách, bạn sẽ cần phải làm:
list(range(1,100))
xrange
một máy phát điện? Nó là một hàm chứa yield
câu lệnh và theo thuật ngữ các hàm như vậy được gọi là các trình tạo.
Hãy nhớ rằng, sử dụng timeit
mô-đun để kiểm tra đoạn mã nhỏ nào nhanh hơn!
$ python -m timeit 'for i in range(1000000):' ' pass'
10 loops, best of 3: 90.5 msec per loop
$ python -m timeit 'for i in xrange(1000000):' ' pass'
10 loops, best of 3: 51.1 msec per loop
Cá nhân, tôi luôn sử dụng .range()
, trừ khi tôi đang xử lý các danh sách thực sự lớn - như bạn có thể thấy, theo thời gian, đối với danh sách một triệu mục, chi phí phụ chỉ là 0,04 giây. Và như Corey chỉ ra, trong Python 3.0 .xrange()
sẽ biến mất và .range()
sẽ cung cấp cho bạn hành vi lặp tốt đẹp.
python -m timeit "for i in xrange(1000000):" " pass"
the extra overhead is only 0.04 seconds
không phải là cách chính xác để xem xét nó, (90.5-51.1)/51.1 = 1.771 times slower
là chính xác bởi vì nó cho rằng nếu đây là vòng lặp cốt lõi của chương trình của bạn thì nó có thể gây tắc nghẽn cho nó. Tuy nhiên, nếu đây là một phần nhỏ thì 1,77x không nhiều.
xrange
chỉ lưu trữ các thông số phạm vi và tạo ra các số theo yêu cầu. Tuy nhiên, việc triển khai C của Python hiện hạn chế các đối số của nó đối với C từ lâu:
xrange(2**32-1, 2**32+1) # When long is 32 bits, OverflowError: Python int too large to convert to C long
range(2**32-1, 2**32+1) # OK --> [4294967295L, 4294967296L]
Lưu ý rằng trong Python 3.0 chỉ có range
và nó hoạt động như 2.x xrange
nhưng không có giới hạn về điểm cuối tối thiểu và tối đa.
xrange trả về một iterator và chỉ giữ một số trong bộ nhớ tại một thời điểm. phạm vi giữ toàn bộ danh sách các số trong bộ nhớ.
xrange
không không trả về một iterator.
and only keeps one number in memory at a time
và nơi đặt phần còn lại xin vui lòng hướng dẫn cho tôi ..
Hãy dành một chút thời gian với Thư viện tham khảo . Bạn càng quen thuộc với nó, bạn càng có thể nhanh chóng tìm thấy câu trả lời cho các câu hỏi như thế này. Đặc biệt quan trọng là một vài chương đầu tiên về các đối tượng và kiểu dựng sẵn.
Ưu điểm của loại xrange là một đối tượng xrange sẽ luôn chiếm cùng một lượng bộ nhớ, bất kể kích thước của phạm vi mà nó đại diện. Không có lợi thế hiệu suất phù hợp.
Một cách khác để tìm thông tin nhanh về cấu trúc Python là chuỗi doc và hàm trợ giúp:
print xrange.__doc__ # def doc(x): print x.__doc__ is super useful
help(xrange)
Tôi bị sốc không ai đọc tài liệu :
Hàm này rất giống với
range()
, nhưng trả về mộtxrange
đối tượng thay vì danh sách. Đây là một loại chuỗi mờ mang lại các giá trị tương tự như danh sách tương ứng, mà không thực sự lưu trữ tất cả chúng cùng một lúc. Lợi thế củaxrange()
hơnrange()
là tối thiểu (vìxrange()
vẫn phải tạo các giá trị khi được yêu cầu) trừ khi sử dụng phạm vi rất lớn trên máy bị thiếu bộ nhớ hoặc khi tất cả các thành phần của phạm vi không bao giờ được sử dụng (chẳng hạn như khi vòng lặp là thường chấm dứt vớibreak
).
phạm vi tạo một danh sách, vì vậy nếu bạn thực hiện phạm vi (1, 10000000), nó sẽ tạo một danh sách trong bộ nhớ với 10000000 phần tử. xrange là một trình tạo, vì vậy nó đánh giá một cách lười biếng.
Điều này mang lại cho bạn hai lợi thế:
MemoryError
.Bạn sẽ tìm thấy lợi thế xrange
hơn range
trong ví dụ đơn giản này:
import timeit
t1 = timeit.default_timer()
a = 0
for i in xrange(1, 100000000):
pass
t2 = timeit.default_timer()
print "time taken: ", (t2-t1) # 4.49153590202 seconds
t1 = timeit.default_timer()
a = 0
for i in range(1, 100000000):
pass
t2 = timeit.default_timer()
print "time taken: ", (t2-t1) # 7.04547905922 seconds
Ví dụ trên không phản ánh bất cứ điều gì tốt hơn đáng kể trong trường hợp xrange
.
Bây giờ hãy nhìn vào trường hợp sau đây, nơi range
thực sự rất chậm, so với xrange
.
import timeit
t1 = timeit.default_timer()
a = 0
for i in xrange(1, 100000000):
if i == 10000:
break
t2 = timeit.default_timer()
print "time taken: ", (t2-t1) # 0.000764846801758 seconds
t1 = timeit.default_timer()
a = 0
for i in range(1, 100000000):
if i == 10000:
break
t2 = timeit.default_timer()
print "time taken: ", (t2-t1) # 2.78506207466 seconds
Với range
, nó đã tạo một danh sách từ 0 đến 100000000 (tốn thời gian), nhưng xrange
là một trình tạo và nó chỉ tạo ra các số dựa trên nhu cầu, nghĩa là, nếu việc lặp lại tiếp tục.
Trong Python-3, việc triển khai range
chức năng giống như xrange
trong Python-2, trong khi chúng đã loại bỏ xrange
trong Python-3
Chúc mừng mã hóa !!
Đó là vì lý do tối ưu hóa.
phạm vi () sẽ tạo danh sách các giá trị từ đầu đến cuối (0 .. 20 trong ví dụ của bạn). Điều này sẽ trở thành một hoạt động đắt tiền trên phạm vi rất lớn.
xrange () mặt khác được tối ưu hóa hơn nhiều. nó sẽ chỉ tính giá trị tiếp theo khi cần (thông qua một đối tượng chuỗi xrange) và không tạo danh sách tất cả các giá trị như phạm vi ().
range(x,y)
trả về một danh sách của mỗi số ở giữa x và y nếu bạn sử dụng một for
vòng lặp, thì range
chậm hơn. Trong thực tế, range
có một phạm vi Index lớn hơn. range(x.y)
sẽ in ra một danh sách tất cả các số ở giữa x và y
xrange(x,y)
trả về xrange(x,y)
nhưng nếu bạn đã sử dụng một for
vòng lặp, thì xrange
nhanh hơn. xrange
có phạm vi Index nhỏ hơn. xrange
sẽ không chỉ in ra xrange(x,y)
mà còn giữ được tất cả các số có trong đó.
[In] range(1,10)
[Out] [1, 2, 3, 4, 5, 6, 7, 8, 9]
[In] xrange(1,10)
[Out] xrange(1,10)
Nếu bạn sử dụng một for
vòng lặp, thì nó sẽ hoạt động
[In] for i in range(1,10):
print i
[Out] 1
2
3
4
5
6
7
8
9
[In] for i in xrange(1,10):
print i
[Out] 1
2
3
4
5
6
7
8
9
Không có nhiều sự khác biệt khi sử dụng các vòng lặp, mặc dù có một sự khác biệt khi chỉ in nó!
phạm vi (): phạm vi (1, 10) trả về danh sách từ 1 đến 10 số và giữ toàn bộ danh sách trong bộ nhớ.
xrange (): Giống như phạm vi (), nhưng thay vì trả về danh sách, trả về một đối tượng tạo ra các số trong phạm vi theo yêu cầu. Đối với vòng lặp, tốc độ này nhanh hơn phạm vi () và hiệu quả bộ nhớ cao hơn. đối tượng xrange () giống như một trình vòng lặp và tạo ra các số theo yêu cầu. (Đánh giá lười biếng)
In [1]: range(1,10)
Out[1]: [1, 2, 3, 4, 5, 6, 7, 8, 9]
In [2]: xrange(10)
Out[2]: xrange(10)
In [3]: print xrange.__doc__
xrange([start,] stop[, step]) -> xrange object
Một số câu trả lời khác đề cập rằng Python 3 đã loại bỏ 2.x range
và đổi tên thành 2.x xrange
thành range
. Tuy nhiên, trừ khi bạn đang sử dụng 3.0 hoặc 3.1 (mà không ai nên làm), thực tế nó là một loại hơi khác.
Như các tài liệu 3.1 nói:
Các đối tượng phạm vi có rất ít hành vi: chúng chỉ hỗ trợ lập chỉ mục, lặp và
len
hàm.
Tuy nhiên, trong 3.2+, range
là một chuỗi đầy đủ, nó hỗ trợ các lát cắt mở rộng và tất cả các phương thức collections.abc.Sequence
có cùng ngữ nghĩa như a list
. *
Và, ít nhất là trong CPython và PyPy (hai triển khai 3.2+ duy nhất hiện có), nó cũng có các triển khai index
và count
phương thức và in
toán tử liên tục theo thời gian (miễn là bạn chỉ truyền cho nó số nguyên). Điều này có nghĩa là viết 123456 in r
là hợp lý trong 3.2+, trong khi ở 2.7 hoặc 3.1 thì đó là một ý tưởng khủng khiếp.
* Thực tế là issubclass(xrange, collections.Sequence)
trả về True
trong 2.6-2.7 và 3.0-3.1 là một lỗi đã được sửa trong 3.2 và không được nhập.
Trong trăn 2.x
phạm vi (x) trả về một danh sách, được tạo trong bộ nhớ với các phần tử x.
>>> a = range(5)
>>> a
[0, 1, 2, 3, 4]
xrange (x) trả về một đối tượng xrange là một trình tạo obj tạo ra các số theo yêu cầu. chúng được tính toán trong vòng lặp for (Đánh giá lười biếng).
Đối với vòng lặp, tốc độ này nhanh hơn một chút so với phạm vi () và hiệu quả bộ nhớ cao hơn.
>>> b = xrange(5)
>>> b
xrange(5)
xrange()
không phải là một máy phát điện. xrange(n)
.__ iter __ () `là.
Khi kiểm tra phạm vi chống xrange trong một vòng lặp (tôi biết tôi nên sử dụng timeit , nhưng điều này đã nhanh chóng bị hack từ bộ nhớ bằng cách sử dụng một ví dụ hiểu danh sách đơn giản) Tôi đã tìm thấy như sau:
import time
for x in range(1, 10):
t = time.time()
[v*10 for v in range(1, 10000)]
print "range: %.4f" % ((time.time()-t)*100)
t = time.time()
[v*10 for v in xrange(1, 10000)]
print "xrange: %.4f" % ((time.time()-t)*100)
cung cấp cho:
$python range_tests.py
range: 0.4273
xrange: 0.3733
range: 0.3881
xrange: 0.3507
range: 0.3712
xrange: 0.3565
range: 0.4031
xrange: 0.3558
range: 0.3714
xrange: 0.3520
range: 0.3834
xrange: 0.3546
range: 0.3717
xrange: 0.3511
range: 0.3745
xrange: 0.3523
range: 0.3858
xrange: 0.3997 <- garbage collection?
Hoặc, sử dụng xrange trong vòng lặp for:
range: 0.4172
xrange: 0.3701
range: 0.3840
xrange: 0.3547
range: 0.3830
xrange: 0.3862 <- garbage collection?
range: 0.4019
xrange: 0.3532
range: 0.3738
xrange: 0.3726
range: 0.3762
xrange: 0.3533
range: 0.3710
xrange: 0.3509
range: 0.3738
xrange: 0.3512
range: 0.3703
xrange: 0.3509
Kiểm tra đoạn mã của tôi có đúng không? Bất kỳ ý kiến về trường hợp chậm hơn của xrange? Hoặc một ví dụ tốt hơn :-)
xrange
có vẻ hơi nhanh hơn, mặc dù với Python 3, sự so sánh hiện đang dư thừa.
timeit
dành cho. Nó đảm nhiệm việc chạy nhiều lần, vô hiệu hóa GC, sử dụng đồng hồ tốt nhất thay vì time
, v.v.
xrange () và phạm vi () trong python hoạt động tương tự như đối với người dùng, nhưng sự khác biệt xuất hiện khi chúng ta đang nói về cách bộ nhớ được phân bổ trong việc sử dụng cả hai hàm.
Khi chúng tôi đang sử dụng phạm vi (), chúng tôi phân bổ bộ nhớ cho tất cả các biến mà nó đang tạo, do đó không nên sử dụng với số lớn hơn. các biến được tạo.
mặt khác, xrange () chỉ tạo ra một giá trị cụ thể và chỉ có thể được sử dụng với vòng lặp for để in tất cả các giá trị cần thiết.
phạm vi tạo ra toàn bộ danh sách và trả về nó. xrange không - nó tạo ra các số trong danh sách theo yêu cầu.
Gì?
range
trả về một danh sách tĩnh khi chạy.
xrange
trả lại mộtobject
(hoạt động như một trình tạo, mặc dù nó chắc chắn không phải là một) từ đó các giá trị được tạo khi và khi được yêu cầu.
Khi nào nên sử dụng?
xrange
nếu bạn muốn tạo một danh sách cho một phạm vi khổng lồ, giả sử là 1 tỷ, đặc biệt là khi bạn có một "hệ thống nhạy cảm với bộ nhớ" như điện thoại di động.range
nếu bạn muốn lặp lại danh sách nhiều lần.PS: Python 3.x của range
chức năng == Python 2.x của xrange
chức năng.
xrange
không trả về một đối tượng máy phát.
Mọi người đã giải thích nó rất nhiều. Nhưng tôi muốn nó nhìn thấy nó cho chính mình. Tôi sử dụng python3. Vì vậy, tôi đã mở trình giám sát tài nguyên (trong Windows!) Và trước tiên, thực hiện lệnh sau trước:
a=0
for i in range(1,100000):
a=a+i
và sau đó kiểm tra thay đổi trong bộ nhớ 'Đang sử dụng'. Nó không đáng kể. Sau đó, tôi chạy đoạn mã sau:
for i in list(range(1,100000)):
a=a+i
Và nó đã chiếm một phần lớn bộ nhớ để sử dụng, ngay lập tức. Và, tôi đã bị thuyết phục. Bạn có thể thử nó cho chính mình.
Nếu bạn đang sử dụng Python 2X, sau đó thay thế 'phạm vi ()' bằng 'xrange ()' trong mã đầu tiên và 'list (phạm vi ())' bằng 'phạm vi ()'.
Từ các tài liệu trợ giúp.
Python 2.7.12
>>> print range.__doc__
range(stop) -> list of integers
range(start, stop[, step]) -> list of integers
Return a list containing an arithmetic progression of integers.
range(i, j) returns [i, i+1, i+2, ..., j-1]; start (!) defaults to 0.
When step is given, it specifies the increment (or decrement).
For example, range(4) returns [0, 1, 2, 3]. The end point is omitted!
These are exactly the valid indices for a list of 4 elements.
>>> print xrange.__doc__
xrange(stop) -> xrange object
xrange(start, stop[, step]) -> xrange object
Like range(), but instead of returning a list, returns an object that
generates the numbers in the range on demand. For looping, this is
slightly faster than range() and more memory efficient.
Python 3.5.2
>>> print(range.__doc__)
range(stop) -> range object
range(start, stop[, step]) -> range object
Return an object that produces a sequence of integers from start (inclusive)
to stop (exclusive) by step. range(i, j) produces i, i+1, i+2, ..., j-1.
start defaults to 0, and stop is omitted! range(4) produces 0, 1, 2, 3.
These are exactly the valid indices for a list of 4 elements.
When step is given, it specifies the increment (or decrement).
>>> print(xrange.__doc__)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'xrange' is not defined
Sự khác biệt là rõ ràng. Trong Python 2.x, range
trả về một danh sách, xrange
trả về một đối tượng xrange có thể lặp lại.
Trong Python 3.x, range
trở thành xrange
Python 2.x và xrange
bị xóa.
Theo yêu cầu quét / in các mục 0-N, phạm vi và xrange hoạt động như sau.
phạm vi () - tạo một danh sách mới trong bộ nhớ và lấy toàn bộ 0 đến N mục (hoàn toàn là N + 1) và in chúng. xrange () - tạo một cá thể iterator quét qua các mục và chỉ giữ các mục gặp phải hiện tại vào bộ nhớ, do đó sử dụng cùng một lượng bộ nhớ mọi lúc.
Trong trường hợp phần tử bắt buộc chỉ phần nào ở đầu danh sách thì nó sẽ tiết kiệm được một lượng thời gian và bộ nhớ tốt.
xrange
không tạo ra một cá thể lặp. Nó tạo ra một xrange
đối tượng, có thể lặp lại, nhưng không phải là một trình lặp lặp gần như (nhưng không hoàn toàn) một chuỗi, giống như một danh sách.
Phạm vi trả về một danh sách trong khi xrange trả về một đối tượng xrange có cùng bộ nhớ bất kể kích thước phạm vi, như trong trường hợp này, chỉ có một phần tử được tạo và khả dụng trên mỗi lần lặp trong khi trong trường hợp sử dụng phạm vi, tất cả các phần tử được tạo cùng một lúc và có sẵn trong bộ nhớ.
Sự khác biệt giảm cho các đối số nhỏ hơn thành range(..)
/ xrange(..)
:
$ python -m timeit "for i in xrange(10111):" " for k in range(100):" " pass"
10 loops, best of 3: 59.4 msec per loop
$ python -m timeit "for i in xrange(10111):" " for k in xrange(100):" " pass"
10 loops, best of 3: 46.9 msec per loop
Trong trường hợp xrange(100)
này chỉ hiệu quả hơn khoảng 20%.
phạm vi: -range sẽ cư trú mọi thứ cùng một lúc. nghĩa là mọi số của phạm vi sẽ chiếm bộ nhớ.
xrange: -xrange là một cái gì đó giống như trình tạo, nó sẽ xuất hiện khi bạn muốn phạm vi số nhưng bạn không muốn chúng được lưu trữ, giống như khi bạn muốn sử dụng cho loop.so bộ nhớ hiệu quả.
Ngoài ra, nếu làm list(xrange(...))
sẽ tương đương với range(...)
.
Thế list
là chậm.
Cũng xrange
thực sự không hoàn thành đầy đủ trình tự
Vì vậy, đó là lý do tại sao nó không phải là một danh sách, nó là một xrange
đối tượng
range()
trong Python 2.x
Hàm này về cơ bản là range()
hàm cũ đã có sẵn trong Python 2.x
và trả về một thể hiện của một list
đối tượng có chứa các phần tử trong phạm vi đã chỉ định.
Tuy nhiên, việc triển khai này quá kém hiệu quả khi bắt đầu một danh sách với một loạt các số. Ví dụ, for i in range(1000000)
sẽ là một lệnh rất tốn kém để thực thi, cả về bộ nhớ và thời gian sử dụng vì nó yêu cầu lưu trữ danh sách này vào bộ nhớ.
range()
trong Python 3.x
và xrange()
trong Python2.x
Python 3.x
giới thiệu một triển khai mới hơn range()
(trong khi triển khai mới hơn đã có sẵn trong Python 2.x
thông quaxrange()
chức năng).
Việc range()
khai thác một chiến lược được gọi là đánh giá lười biếng. Thay vì tạo một danh sách lớn các phần tử trong phạm vi, triển khai mới hơn giới thiệu lớp range
, một đối tượng nhẹ đại diện cho các phần tử cần thiết trong phạm vi đã cho, mà không lưu trữ chúng rõ ràng trong bộ nhớ (điều này nghe có vẻ giống như máy phát điện nhưng khái niệm đánh giá lười biếng là khác nhau).
Ví dụ, xem xét những điều sau đây:
# Python 2.x
>>> a = range(10)
>>> type(a)
<type 'list'>
>>> b = xrange(10)
>>> type(b)
<type 'xrange'>
và
# Python 3.x
>>> a = range(10)
>>> type(a)
<class 'range'>
Xem bài này để tìm sự khác biệt giữa phạm vi và xrange:
Để trích:
range
trả về chính xác những gì bạn nghĩ: một danh sách các số nguyên liên tiếp, có độ dài xác định bắt đầu bằng 0.xrange
, tuy nhiên, trả về một "đối tượng xrange" , hoạt động rất nhiều như một trình vòng lặp
xrange
không phải là một trình vòng lặp. Danh sách được trả về bởi range
không hỗ trợ phép lặp (một danh sách gần như là ví dụ mẫu của một lần lặp). Lợi ích tổng thể của xrange
không phải là "tối thiểu". Và như thế.