ความแตกต่างระหว่างฟังก์ชั่น range และ xrange ใน Python 2.X คืออะไร?


719

เห็นได้ชัดว่า xrange เร็วกว่า แต่ฉันไม่รู้ว่าทำไมมันเร็วกว่า (และไม่มีข้อพิสูจน์ใด ๆ นอกเหนือจากประวัติที่ผ่านมาจนถึงเร็วกว่า) หรืออะไรที่นอกเหนือจากนั้นแตกต่างกัน

for i in range(0, 20):
for i in xrange(0, 20):

คำตอบ:


817

ใน Python 2.x:

  • rangeสร้างรายการดังนั้นถ้าคุณrange(1, 10000000)สร้างรายการในหน่วยความจำที่มี9999999องค์ประกอบ

  • xrange เป็นวัตถุลำดับที่ประเมินความเกียจคร้าน

ในหลาม 3 rangeไม่เทียบเท่าหลามของและจะได้รับรายการที่คุณต้องใช้xrangelist(range(...))


65
xrange นั้นไม่ใช่ตัวกำเนิดไฟฟ้าที่แน่นอน แต่มันประเมินค่าความเกียจคร้านและทำหน้าที่เหมือนเครื่องกำเนิดไฟฟ้า
Vaibhav Mishra

47
xrange(x).__iter__()เป็นเครื่องกำเนิดไฟฟ้า
เพิ่ม

34
ทำไมพวกเขาถึงทำ xrange แทนที่จะทำช่วงที่ขี้เกียจ?
Rob Grant

22
@ RobertGrant พวกเขาทำ ใน Python 3 (พวกเขาไม่สามารถทำเช่นนั้นได้ในบรรทัด Python 2.x เนื่องจากการเปลี่ยนแปลงทั้งหมดจะต้องเข้ากันได้ย้อนหลัง)
Paul Draper

12
@Ratul หมายความว่าแต่ละรายการiได้รับการประเมินตามความต้องการมากกว่าที่จะเริ่มต้น
Onilol

223

range สร้างรายการดังนั้นถ้าคุณrange(1, 10000000)สร้างรายการในหน่วยความจำที่มี9999999องค์ประกอบ

xrange เป็นเครื่องกำเนิดไฟฟ้าดังนั้นจึงเป็นวัตถุลำดับคือการประเมินที่ขี้เกียจ

นี่คือความจริง แต่ในหลาม 3 .range()จะได้รับการดำเนินการโดยงูหลาม .xrange()2 หากคุณต้องการสร้างรายการจริงคุณจะต้องทำ:

list(range(1,100))

3
ฉันไม่เห็นว่าเป็นปัญหาใหญ่ (เกี่ยวกับการแบ่งแอปพลิเคชั่นที่มีอยู่) เนื่องจาก range เป็นส่วนใหญ่สำหรับการสร้างดัชนีที่จะใช้เป็นลูปเป็น "สำหรับ i ในช่วง (1, 10):"
Benjamin Autin

10
+1 ขอบคุณสำหรับคำตอบนี้ข้อมูลเกี่ยวกับ Python 3 ที่แทนที่ช่วงด้วย xrange นั้นมีประโยชน์มาก ที่จริงผมบอกคนที่จะใช้ xrange แทนหรือช่วงและพวกเขาบอกว่ามันไม่ได้เรื่องในหลาม 3 ดังนั้นฉัน Google ค้นหาข้อมูลเพิ่มเติมและคำตอบนี้ขึ้นมา :)
Cervo

เกิดอะไรขึ้นกับการเรียกxrangeตัวกำเนิด มันเป็นฟังก์ชั่นที่มีyieldคำสั่งและตามคำศัพท์ฟังก์ชั่นดังกล่าวเรียกว่ากำเนิด
winterlight

@Winterlight ให้คิดว่าคำที่ถูกต้องคือ iterator เครื่องกำเนิดไฟฟ้าควรจะได้รับเช่นกัน
McSinyx

112

จำไว้ว่าใช้timeitโมดูลเพื่อทดสอบโค้ดขนาดเล็กที่เร็วกว่านี้!

$ 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

ส่วนตัวผมมักจะใช้.range()เว้นแต่ผมจัดการกับมันรายการใหญ่ - ที่คุณสามารถดูเวลาที่ชาญฉลาดสำหรับรายชื่อของล้านรายการให้ค่าใช้จ่ายเพิ่มเติมเป็นเพียง 0.04 วินาที และตามที่ Corey ชี้ให้เห็นใน Python 3.0 .xrange()จะหายไปและ.range()จะให้พฤติกรรมตัววนซ้ำที่ดีอยู่ดี


12
+1 สำหรับตัวอย่าง timeit หมายเหตุ: หากต้องการใช้งานใน windows cmd จำเป็นต้องใช้เครื่องหมายคำพูดคู่เช่น "ดังนั้นโค้ดจะเป็นpython -m timeit "for i in xrange(1000000):" " pass"
stalk

10
ประโยชน์หลักของ xrange คือหน่วยความจำไม่ใช่เวลา
endolith

3
+1 สำหรับคำตอบที่ปฏิบัติ: ช่วงใช้เว้นแต่ใหญ่ BTW พวกเขามีแนวคิดเหมือนกันถูกต้องหรือไม่ แปลกไม่มีคำตอบคาถาที่ออก
Bob Stein

6
ถ้า xrange เร็วกว่าและไม่จำหน่วยความจำทำไมจึงใช้ช่วง?
Austin Mohr

8
ฉันเห็นด้วยกับคำสั่งของคุณโดยทั่วไป แต่การประเมินของคุณไม่ถูกต้อง: the extra overhead is only 0.04 secondsไม่ใช่วิธีที่ถูกต้องในการดูมัน(90.5-51.1)/51.1 = 1.771 times slowerถูกต้องเพราะมันบ่งบอกว่าหากนี่เป็นแกนหลักของโปรแกรมของคุณมันอาจทำให้เกิดปัญหาคอขวด อย่างไรก็ตามถ้านี่เป็นส่วนเล็ก ๆ แล้ว 1.77x ก็ไม่มาก
chacham15

65

xrangeเก็บเฉพาะช่วงพารามิเตอร์และสร้างตัวเลขตามต้องการ อย่างไรก็ตามการนำ C ไปใช้งานของ Python นั้น จำกัด args ไว้ที่ C longs:

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]

โปรดทราบว่าใน Python 3.0 มีเพียงrangeและจะทำงานเหมือน 2.x xrangeแต่ไม่มีข้อ จำกัด เกี่ยวกับจุดสิ้นสุดขั้นต่ำและสูงสุด


39

xrange ส่งคืนตัววนซ้ำและเก็บหมายเลขหนึ่งไว้ในหน่วยความจำพร้อมกัน ช่วงเก็บรายการตัวเลขทั้งหมดในหน่วยความจำ


9
xrangeไม่ได้กลับ iterator
abarnert

and only keeps one number in memory at a timeและสถานที่ที่เหลืออยู่โปรดแนะนำฉัน ..
SIslam

5
@SIslam หากรู้ว่าจุดเริ่มต้นจุดสิ้นสุดและกระแสสามารถคำนวณได้ครั้งละหนึ่งจุด
Justin Meiners

30

อย่าใช้เวลาบางคนที่มีการอ้างอิงห้องสมุด ยิ่งคุณคุ้นเคยกับมันมากเท่าไหร่คุณก็ยิ่งสามารถค้นหาคำตอบของคำถามได้เร็วขึ้นเท่านั้น สิ่งสำคัญอย่างยิ่งคือบทแรก ๆ เกี่ยวกับวัตถุและประเภทในตัว

ข้อดีของประเภท xrange ก็คือวัตถุ xrange จะใช้หน่วยความจำในปริมาณเท่ากันเสมอไม่ว่าขนาดของช่วงจะเป็นเท่าใด ไม่มีข้อได้เปรียบด้านประสิทธิภาพที่สอดคล้องกัน

อีกวิธีในการค้นหาข้อมูลอย่างรวดเร็วเกี่ยวกับโครงสร้างของ Python คือ docstring และฟังก์ชันช่วยเหลือ:

print xrange.__doc__ # def doc(x): print x.__doc__ is super useful
help(xrange)

1
ห้องสมุดดี แต่ไม่ง่ายเสมอไปที่จะได้คำตอบสำหรับคำถามที่คุณมี
Teifion

2
ไปที่การอ้างอิงไลบรารีกด ctrl + f ค้นหาช่วงและคุณจะได้รับสองผลลัพธ์ การหาคำตอบสำหรับคำถามนี้ไม่ใช่ความพยายามมากนัก
David Locke

1
การอ้างอิงไลบรารีไม่ทำงาน คุณช่วยอัพเดทได้ไหม
mk ..

14

ฉันช็อคไม่มีใครอ่านหมอ :

ฟังก์ชั่นนี้คล้ายกันมากrange()แต่ส่งคืนxrangeวัตถุแทนที่จะเป็นรายการ นี่เป็นประเภทลำดับทึบแสงซึ่งให้ค่าเหมือนกับรายการที่สอดคล้องกันโดยไม่ต้องเก็บค่าทั้งหมดพร้อมกัน ข้อได้เปรียบของxrange()over range()มีน้อยที่สุด (เนื่องจากxrange()ยังต้องสร้างค่าเมื่อถูกถาม) ยกเว้นเมื่อช่วงที่มีขนาดใหญ่มากถูกใช้บนเครื่องที่มีหน่วยความจำที่หิวโหยหรือเมื่อองค์ประกอบทั้งหมดของช่วงไม่เคยถูกใช้ (เช่นเมื่อลูปเป็น มักจะสิ้นสุดด้วยbreak)


13

range สร้างรายการดังนั้นถ้าคุณทำ range (1, 10,000000) มันจะสร้าง list ในหน่วยความจำที่มีองค์ประกอบ 10,000000 xrange เป็นเครื่องกำเนิดไฟฟ้าดังนั้นจึงประเมินความเกียจคร้าน

สิ่งนี้ทำให้คุณได้เปรียบสองประการ:

  1. คุณสามารถวนซ้ำรายการที่ยาวขึ้นโดยไม่ได้รับ MemoryErrorคุณสามารถย้ำรายการอีกต่อไปโดยไม่ได้รับ
  2. ในขณะที่มันแก้ปัญหาแต่ละหมายเลขอย่างเกียจคร้านถ้าคุณหยุดการทำซ้ำเร็วคุณจะไม่เสียเวลาในการสร้างรายการทั้งหมด

12

คุณจะพบข้อได้เปรียบxrangeมากกว่าrangeในตัวอย่างง่ายๆนี้:

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

ตัวอย่างข้างต้นไม่ได้สะท้อนสิ่งใดที่ดีกว่าในกรณีของ xrangeตัวอย่างข้างต้นไม่ได้สะท้อนให้เห็นถึงสิ่งที่ดีขึ้นอย่างมีนัยสำคัญในกรณีของ

ตอนนี้ดูที่กรณีดังต่อไปที่จะถูกจริงๆช้าเมื่อเทียบกับrangexrange

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

ด้วยrangeมันสร้างรายการจาก 0 ถึง 100000000 (ใช้เวลานาน) แต่xrangeเป็นตัวกำเนิดและสร้างเฉพาะตัวเลขตามความต้องการนั่นคือถ้าการวนซ้ำยังคงดำเนินต่อไป

ใน Python-3 การใช้งานของrangeฟังก์ชั่นนั้นเหมือนกับxrangeใน Python-2 ในขณะที่ใช้งานได้xrangeใน Python-3

Happy Coding !!


11

เป็นเหตุผลการเพิ่มประสิทธิภาพ

range () จะสร้างรายการค่าตั้งแต่ต้นจนจบ (0 .. 20 ในตัวอย่างของคุณ) นี่จะเป็นการดำเนินการที่มีราคาแพงในช่วงที่มีขนาดใหญ่มาก

xrange () ในทางกลับกันจะได้รับการปรับให้เหมาะสมยิ่งขึ้น มันจะคำนวณเฉพาะค่าถัดไปเมื่อจำเป็น (ผ่านวัตถุลำดับ xrange) และไม่ได้สร้างรายการของค่าทั้งหมดเช่น range ()


9

range(x,y)ส่งกลับรายการของแต่ละหมายเลขในระหว่าง x และ y หากคุณใช้การforวนซ้ำแล้วrangeช้าลง ในความเป็นจริงrangeมีช่วงดัชนีที่ใหญ่กว่า range(x.y)จะพิมพ์รายการหมายเลขทั้งหมดในระหว่าง x และ y

xrange(x,y)ส่งคืนxrange(x,y)แต่ถ้าคุณใช้การforวนซ้ำxrangeจะเร็วกว่า xrangeมีช่วงดัชนีที่เล็กกว่า xrangeจะไม่เพียงพิมพ์ออกมาxrange(x,y)แต่ยังคงเก็บหมายเลขทั้งหมดที่อยู่ในนั้น

[In] range(1,10)
[Out] [1, 2, 3, 4, 5, 6, 7, 8, 9]
[In] xrange(1,10)
[Out] xrange(1,10)

ถ้าคุณใช้การforวนซ้ำมันจะทำงานได้

[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

มีความแตกต่างไม่มากเมื่อใช้ลูปแม้ว่าจะมีความแตกต่างเมื่อพิมพ์มัน!


8

range (): range (1, 10) ส่งคืนรายการจากหมายเลข 1 ถึง 10 และเก็บรายการทั้งหมดไว้ในหน่วยความจำ

xrange (): Like range () แต่แทนที่จะส่งคืนรายการให้ส่งคืนออบเจ็กต์ที่สร้างตัวเลขในช่วงตามต้องการ สำหรับการวนซ้ำนี้จะเร็วกว่า range () และประสิทธิภาพของหน่วยความจำมากขึ้นเล็กน้อย วัตถุ xrange () เหมือนตัววนซ้ำและสร้างตัวเลขตามต้องการ (Lazy Evaluation)

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

6

บางส่วนของคำตอบอื่น ๆ พูดถึงว่างูหลาม 3 กำจัด 2.x ของrangeและเปลี่ยนชื่อ 2.x ของการxrange rangeอย่างไรก็ตามถ้าคุณใช้ 3.0 หรือ 3.1 (ซึ่งไม่มีใครควร) มันเป็นประเภทที่แตกต่างกันบ้าง

ในฐานะที่เป็น3.1 เอกสารกล่าวว่า:

วัตถุช่วงมีพฤติกรรมน้อยมาก: รองรับเฉพาะการทำดัชนีการวนซ้ำและlenฟังก์ชัน

อย่างไรก็ตามใน 3.2+, rangeเป็นเต็มลำดับที่จะสนับสนุนการขยายชิ้นและทุกวิธีการของที่มีความหมายเช่นเดียวกับcollections.abc.Sequence * * * *list

และอย่างน้อยก็ใน CPython และ PyPy (การใช้งานเพียง 3.2+ ที่มีอยู่ในปัจจุบัน) มันยังมีการใช้งานตลอดเวลาของindexและcountวิธีการและตัวinดำเนินการ (ตราบใดที่คุณผ่านจำนวนเต็มเท่านั้น) ซึ่งหมายความว่าการเขียน123456 in rมีความเหมาะสมใน 3.2+ ในขณะที่ 2.7 หรือ 3.1 จะเป็นความคิดที่น่ากลัว


* ความจริงที่issubclass(xrange, collections.Sequence)ส่งกลับTrueใน 2.6-2.7 และ 3.0-3.1 เป็นจุดบกพร่องที่ได้รับการแก้ไขใน 3.2 และไม่ได้รับการย้อนกลับ


6

ในหลาม 2.x

range (x)ส่งคืนรายการที่สร้างขึ้นในหน่วยความจำที่มีองค์ประกอบ x

>>> a = range(5)
>>> a
[0, 1, 2, 3, 4]

xrange (x)ส่งคืนวัตถุ xrange ซึ่งเป็นตัวกำเนิด obj ซึ่งสร้างตัวเลขตามต้องการ พวกมันถูกคำนวณระหว่าง for-loop (Lazy Evaluation)

สำหรับการวนซ้ำนี้จะเร็วกว่า range () เล็กน้อยและมีประสิทธิภาพของหน่วยความจำมากขึ้น

>>> b = xrange(5)
>>> b
xrange(5)

xrange()ไม่ใช่เครื่องกำเนิดไฟฟ้า xrange(n).__ iter __ () `คือ
th3an0maly

5

เมื่อทำการทดสอบกับ xrange ในลูป (ฉันรู้ว่าฉันควรใช้timeitแต่นี่ถูกแฮ็กอย่างรวดเร็วจากหน่วยความจำโดยใช้ตัวอย่างรายการเข้าใจง่าย) ฉันพบสิ่งต่อไปนี้:

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)

ซึ่งจะช่วยให้:

$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?

หรือใช้ xrange ใน for for loop:

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

การทดสอบตัวอย่างของฉันถูกต้องหรือไม่ ความคิดเห็นใด ๆ ในอินสแตนซ์ที่ช้าลงของ xrange? หรือตัวอย่างที่ดีกว่า :-)


2
การใช้เกณฑ์มาตรฐานเช่นนี้หนึ่งครั้งไม่ได้ให้ผลลัพธ์เวลาที่แน่นอน มีความแปรปรวนอยู่เสมอ .. อาจเป็นได้ทั้ง GC หรือกระบวนการอื่นขโมย CPU ... อะไรก็ได้ นั่นเป็นสาเหตุที่ทำให้การวัดประสิทธิภาพมักจะรัน 10-100-1000 -...
Vajk Hermecz

นี่เป็นเพียงตัวอย่างสั้น ๆ ที่พิมพ์ออกมา - ฉันวิ่งไปสองสามครั้ง แต่เหลือแค่ประมาณ 100 และxrangeดูเหมือนจะเร็วขึ้นเล็กน้อยแม้ว่า Python 3 จะมีการเปรียบเทียบซ้ำซ้อน
Dave Everitt

3
นี่คือสิ่งที่timeitมีไว้เพื่อ มันดูแลการทำงานหลาย ๆ ครั้ง, ปิดการใช้งาน GC, ใช้นาฬิกาที่ดีที่สุดแทนtimeฯลฯ
abarnert

4

xrange () และ range () ใน python ทำงานคล้ายกับผู้ใช้ แต่ความแตกต่างเกิดขึ้นเมื่อเราพูดถึงวิธีการจัดสรรหน่วยความจำในการใช้ทั้งฟังก์ชั่น

เมื่อเราใช้ range () เราจัดสรรหน่วยความจำสำหรับตัวแปรทั้งหมดที่กำลังสร้างดังนั้นจึงไม่แนะนำให้ใช้กับหมายเลขที่ใหญ่กว่า ของตัวแปรที่จะสร้าง

xrange () ในทางกลับกันจะสร้างค่าเฉพาะในแต่ละครั้งเท่านั้นและสามารถใช้กับ for สำหรับวนรอบเพื่อพิมพ์ค่าทั้งหมดที่ต้องการ




2

อะไร?
rangeส่งคืนรายการสแตติกที่รันไทม์
xrangeส่งกลับค่าobject(ซึ่งทำหน้าที่เหมือนเครื่องกำเนิดไฟฟ้าแม้ว่าจะไม่ใช่หนึ่งอย่างแน่นอน) ซึ่งค่าจะถูกสร้างขึ้นตามและเมื่อจำเป็น

จะใช้เมื่อใด

  • ใช้ xrangeหากคุณต้องการสร้างรายการสำหรับช่วงขนาดมหึมาพูดได้ 1 พันล้านโดยเฉพาะเมื่อคุณมี "ระบบที่มีความสำคัญต่อความจำ" เช่นโทรศัพท์มือถือ
  • ใช้rangeหากคุณต้องการวนซ้ำในรายการหลาย ๆ ครั้ง

งูหลามของ 3.x: PS rangeฟังก์ชั่น == หลาม 2.x ของxrangeฟังก์ชั่น


xrangeไม่ส่งคืนวัตถุเครื่องกำเนิด
abarnert

ถ้าฉันเข้าใจอย่างถูกต้องนั่นคือวิธีอธิบายไว้ที่นี่ (สำหรับ Python 2.x): wiki.python.org/moin/Generators
kmario23

จากนั้นวิกินั้นผิด (ฉันไม่รู้ว่าใคร "SH" คือใครที่เพิ่มและเซ็นชื่อความคิดเห็นนั้น) เอกสารทางการนั้นถูกต้อง คุณสามารถทดสอบด้วยตัวเองและดูว่ามันเป็นตัวกำเนิดหรือลำดับ
abarnert

ตกลง. แต่มันยังคงสับสนหลังจากอ่านสิ่งนี้: stackoverflow.com/questions/135041/…
kmario23

1
คำถามที่สนุกคือสิ่งที่ต้องทำเมื่อล่ามไม่เห็นด้วยกับเอกสารอย่างเป็นทางการหรือล่ามที่แตกต่างกัน ... แต่โชคดีที่มันไม่ได้เกิดขึ้นบ่อยเกินไป ...
abarnert

2

ทุกคนได้อธิบายอย่างมาก แต่ฉันต้องการให้มันดูด้วยตัวเอง ฉันใช้ python3 ดังนั้นฉันเปิดมอนิเตอร์ทรัพยากร (ใน Windows!) และก่อนอื่นให้ดำเนินการคำสั่งต่อไปนี้ก่อน:

a=0
for i in range(1,100000):
    a=a+i

จากนั้นตรวจสอบการเปลี่ยนแปลงในหน่วยความจำ 'ใช้งาน' มันไม่มีนัยสำคัญ จากนั้นฉันรันรหัสต่อไปนี้:

for i in list(range(1,100000)):
    a=a+i

และใช้หน่วยความจำก้อนใหญ่ทันที และฉันก็มั่นใจ คุณสามารถลองด้วยตัวเอง

หากคุณใช้ Python 2X ให้แทนที่ 'range ()' ด้วย 'xrange ()' ในรหัสแรกและ 'list (range ())' ด้วย 'range ()'


2

จากเอกสารช่วยเหลือ

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

ความแตกต่างชัดเจน ใน Python 2.x rangeส่งคืนรายการxrangeส่งคืนอ็อบเจกต์ xrange ที่สามารถทำซ้ำได้

ใน Python 3.x, rangeกลายเป็นxrangePython 2.x, และxrangeถูกลบออก


1

ตามข้อกำหนดสำหรับการสแกน / การพิมพ์รายการ 0-N ช่วงและ xrange ทำงานดังต่อไปนี้

range () - สร้างรายการใหม่ในหน่วยความจำและนำรายการทั้งหมด 0 ถึง N (ทั้งหมด N + 1) และพิมพ์ xrange () - สร้างอินสแตนซ์ตัววนซ้ำที่สแกนรายการต่างๆและเก็บเฉพาะรายการที่พบในปัจจุบันลงในหน่วยความจำดังนั้นจึงใช้หน่วยความจำจำนวนเท่ากันตลอดเวลา

ในกรณีที่องค์ประกอบที่ต้องการค่อนข้างอยู่ที่จุดเริ่มต้นของรายการเท่านั้นจากนั้นจะช่วยประหยัดเวลาและหน่วยความจำได้ดี


1
xrangeไม่สร้างอินสแตนซ์ตัววนซ้ำ มันสร้างxrangeวัตถุซึ่งสามารถทำซ้ำได้ แต่ไม่ใช่ตัววนซ้ำ - เกือบ (แต่ไม่มาก) ลำดับเหมือนรายการ
abarnert

1

Rangeส่งคืนรายการในขณะที่xrangeส่งคืนวัตถุxrangeซึ่งใช้หน่วยความจำเดียวกันโดยไม่คำนึงถึงขนาดของช่วงเช่นเดียวกับในกรณีนี้จะมีเพียงองค์ประกอบเดียวเท่านั้นที่ถูกสร้างขึ้นและพร้อมใช้งานต่อการทำซ้ำในขณะที่ มีอยู่ในหน่วยความจำ


1

ความแตกต่างลดลงสำหรับอาร์กิวเมนต์ที่น้อยกว่าไปยัง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

ในกรณีนี้xrange(100)มีประสิทธิภาพมากกว่าประมาณ 20% เท่านั้น


1

ช่วง: - ช่วงจะเติมทุกอย่างในครั้งเดียวซึ่งหมายความว่าทุกช่วงของจำนวนจะครอบครองหน่วยความจำ

xrange: -xrange เป็นเครื่องกำเนิดไฟฟ้ามันจะเข้ามาในรูปภาพเมื่อคุณต้องการช่วงของตัวเลข แต่คุณไม่ต้องการให้มันถูกเก็บไว้เช่นเมื่อคุณต้องการใช้สำหรับหน่วยความจำ loop.so


1

นอกจากนี้หากทำเช่นlist(xrange(...))นั้นจะเทียบเท่าrange(...)จะเทียบเท่ากับ

ดังนั้น listช้า

ด้วย xrangeไม่เสร็จสมบูรณ์ตามลำดับ

นั่นคือสาเหตุที่มันไม่ใช่รายการ แต่เป็นxrangeวัตถุ


1

range() ใน Python 2.x

ฟังก์ชั่นนี้เป็นฟังก์ชั่นเก่าrange()ที่มีอยู่ใน Python 2.xและส่งคืนอินสแตนซ์ของlistวัตถุที่มีองค์ประกอบในช่วงที่ระบุ

อย่างไรก็ตามการใช้งานนี้ไม่มีประสิทธิภาพมากเกินไปเมื่อมันมาถึงการเริ่มต้นรายการที่มีช่วงของตัวเลข ตัวอย่างเช่นfor i in range(1000000)จะเป็นคำสั่งที่มีราคาแพงมากในการดำเนินการทั้งในแง่ของหน่วยความจำและการใช้เวลาเนื่องจากมันต้องการหน่วยเก็บข้อมูลของรายการนี้ในหน่วยความจำ


range()ใน Python 3.xและxrange()Python2.x

Python 3.xแนะนำการใช้งานที่ใหม่กว่าของrange()(ในขณะที่การใช้งานที่ใหม่กว่านั้นมีอยู่ใน Python 2.xผ่านทางxrange()ฟังก์ชั่น)

การrange()ใช้ประโยชน์จากกลยุทธ์ที่เรียกว่าการประเมินผลที่ขี้เกียจ แทนที่จะสร้างรายการองค์ประกอบขนาดใหญ่ในระยะการใช้งานใหม่แนะนำคลาสrangeวัตถุที่มีน้ำหนักเบาที่แสดงถึงองค์ประกอบที่จำเป็นในช่วงที่กำหนดโดยไม่เก็บไว้ในหน่วยความจำอย่างชัดเจน (นี่อาจฟังดูคล้ายกับเครื่องกำเนิดไฟฟ้า แตกต่างกัน)


เป็นตัวอย่างพิจารณาดังต่อไปนี้:

# Python 2.x
>>> a = range(10)
>>> type(a)
<type 'list'>
>>> b = xrange(10)
>>> type(b)
<type 'xrange'>

และ

# Python 3.x
>>> a = range(10)
>>> type(a)
<class 'range'>

-2

ดูโพสต์นี้เพื่อค้นหาความแตกต่างระหว่างช่วงและ xrange:

อ้างถึง:

rangeส่งคืนสิ่งที่คุณคิด: รายการของจำนวนเต็มต่อเนื่องของความยาวที่กำหนดเริ่มต้นด้วย 0 xrangeอย่างไรก็ตามส่งคืน"วัตถุ xrange"ซึ่งทำหน้าที่ได้อย่างมากเช่นตัววนซ้ำ


2
ฉันรู้ว่านี่คือ 5 ปี แต่โพสต์ที่ผิดเกี่ยวกับเกือบทุกอย่าง xrangeไม่ใช่ตัววนซ้ำ รายการที่ส่งคืนโดยrangeรองรับการทำซ้ำ (รายการเป็นตัวอย่างต้นแบบของการทำซ้ำได้ค่อนข้างมาก) ประโยชน์โดยรวมของการใช้งานxrangeนั้นไม่ "น้อยที่สุด" และอื่น ๆ
abarnert
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.