python - पायथन 2.X में रेंज और xrange कार्यों के बीच क्या अंतर है?




loops python-2.x (19)

स्पष्ट रूप से xrange तेज़ है लेकिन मुझे नहीं पता कि यह तेज़ क्यों है (और अब तक यह स्पष्ट नहीं है कि यह तेज़ है) या इसके अलावा इसके अलावा क्या अलग है

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

रेंज एक सूची बनाता है, इसलिए यदि आप range(1, 10000000) यह 9999999 तत्वों के साथ मेमोरी में एक सूची बनाता है।

xrange एक जेनरेटर है, इसलिए यह एक अनुक्रम वस्तु है जो आलसी मूल्यांकन करती है।

यह सच है, लेकिन पायथन 3 में, पायथन 2 xrange () द्वारा लागू किया जाएगा। यदि आपको वास्तव में सूची जेनरेट करने की आवश्यकता है, तो आपको यह करना होगा:

list(range(1,100))

रेंज एक सूची बनाता है, इसलिए यदि आप रेंज (1, 10000000) करते हैं तो यह 10000000 तत्वों के साथ स्मृति में एक सूची बनाता है। xrange एक जेनरेटर है, इसलिए यह आलसी मूल्यांकन करता है।

यह आपको दो फायदे लाता है:

  1. आप MemoryError प्राप्त किए बिना लंबी सूचियां MemoryError
  2. चूंकि यह प्रत्येक संख्या को आलसी ढंग से हल करता है, अगर आप जल्दी ही इसे रोकते हैं, तो आप पूरी सूची बनाने में समय बर्बाद नहीं करेंगे।

xrange एक इटरेटर का उपयोग करता है (फ्लाई पर मूल्य उत्पन्न करता है), रेंज एक सूची देता है।


xrange एक पुनरावर्तक देता है और एक समय में केवल एक संख्या स्मृति में रहता है। रेंज संख्याओं की पूरी सूची स्मृति में रखती है।


इस सरल उदाहरण में आपको 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 मामले में कुछ भी बेहतर रूप से बेहतर नहीं दर्शाता है।

अब निम्न मामले को देखें जहां xrange की तुलना में range वास्तव में वास्तव में धीमी है।

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 एक जेनरेटर है और यह केवल आवश्यकता के आधार पर संख्याएं उत्पन्न करता है, यानी, यदि पुनरावृत्ति जारी है।

पायथन -3 में, range कार्यक्षमता का कार्यान्वयन पायथन xrange में xrange समान है, जबकि उन्होंने पायथन xrange में xrange दूर किया है

हैप्पी कोडिंग !!


कुछ अन्य उत्तरों का उल्लेख है कि पायथन 3 ने 2.x की range हटा दिया और 2.x के xrange को range बदल दिया। हालांकि, जब तक कि आप 3.0 या 3.1 का उपयोग नहीं कर रहे हैं (जो कोई भी नहीं होना चाहिए), यह वास्तव में कुछ अलग प्रकार है।

चूंकि 3.1 डॉक्स कहते हैं:

रेंज ऑब्जेक्ट्स बहुत कम व्यवहार करते हैं: वे केवल अनुक्रमण, पुनरावृत्ति और len समारोह का समर्थन करते हैं।

हालांकि, 3.2+ में, range एक पूर्ण अनुक्रम है-यह विस्तारित स्लाइस का समर्थन करता है, और collections.abc.Sequence सभी तरीकों का collections.abc.Sequence करता है। list के समान अर्थशास्त्र के साथ समानता। *

और, कम से कम सीपीथॉन और पीईपीई (वर्तमान में केवल दो 3.2+ कार्यान्वयन जो वर्तमान में मौजूद हैं) में, यह index और count विधियों और ऑपरेटर में निरंतर समय कार्यान्वयन भी करता है (जब तक आप इसे केवल पूर्णांक पास करते हैं)। इसका मतलब है कि 123456 in r लिखना 3.2+ में उचित है, जबकि 2.7 या 3.1 में यह एक भयानक विचार होगा।

* तथ्य यह है कि issubclass(xrange, collections.Sequence) 2.6-2.7 और 3.0-3.1 में True देता है एक बग है जिसे 3.2 में तय किया गया था और बैकपोर्ड नहीं किया गया था।


ग्राफिकल विश्लेषण के साथ रेंज और xrange के बीच तुलना के लिए निम्नलिखित पोस्ट पढ़ें।

पायथन रेंज बनाम xrange


जब एक लूप में xrange के खिलाफ परीक्षण सीमा (मुझे पता है कि मुझे टाइमिट का उपयोग करना चाहिए, लेकिन यह एक सरल सूची समझ उदाहरण का उपयोग करके स्मृति से तेजी से हैक किया गया था) मुझे निम्न मिला:

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 का उपयोग कर:

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 के धीमे उदाहरण पर कोई टिप्पणी? या एक बेहतर उदाहरण :-)


पायथन में xrange () और रेंज () उपयोगकर्ता के लिए समान रूप से काम करता है, लेकिन अंतर तब आता है जब हम दोनों फ़ंक्शन का उपयोग करने में स्मृति आवंटित करने के बारे में बात कर रहे हैं।

जब हम रेंज का उपयोग कर रहे हैं () हम उत्पन्न होने वाले सभी चर के लिए स्मृति आवंटित करते हैं, इसलिए बड़ी संख्या के साथ उपयोग करने की अनुशंसा नहीं की जाती है। उत्पन्न होने के लिए चर के।

दूसरी तरफ xrange () एक समय में केवल एक विशेष मूल्य उत्पन्न करता है और केवल लूप के साथ आवश्यक सभी मानों को मुद्रित करने के लिए उपयोग किया जा सकता है।


मैं किसी को भी doc नहीं देखता हूँ:

यह फ़ंक्शन range() समान है, लेकिन सूची के बजाय एक xrange ऑब्जेक्ट देता है। यह एक अपारदर्शी अनुक्रम प्रकार है जो समान सूची के समान मूल्यों को समान रूप से संग्रहीत किए बिना समान सूची के रूप में उत्पन्न करता है। xrange() से अधिक range() का लाभ न्यूनतम है (चूंकि xrange() अभी भी उनके लिए पूछे जाने पर मान बनाना है) सिवाय इसके कि जब स्मृति-भूखे मशीन पर बहुत बड़ी रेंज का उपयोग किया जाता है या जब सभी श्रेणी के तत्व होते हैं कभी भी इस्तेमाल नहीं किया जाता है (जैसे कि जब लूप आमतौर पर break साथ समाप्त होता है)।


यह अनुकूलन कारणों के लिए है।

श्रेणी () प्रारंभ से अंत तक मूल्यों की एक सूची तैयार करेगी (0 .. 20 आपके उदाहरण में)। यह बहुत बड़ी श्रृंखलाओं पर एक महंगा ऑपरेशन बन जाएगा।

दूसरी तरफ xrange () अधिक अनुकूलित है। यह आवश्यक होने पर केवल अगले मान की गणना करेगा (एक xrange अनुक्रम वस्तु के माध्यम से) और श्रेणी () करता है जैसे सभी मानों की एक सूची नहीं बनाता है।


याद रखें, कोड के छोटे स्निप्स तेज़ी से जांचने के लिए टाइमिट मॉड्यूल का उपयोग करें!

$ 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

निजी तौर पर, मैं हमेशा रेंज () का उपयोग करता हूं, जब तक कि मैं वास्तव में बड़ी सूचियों से निपट नहीं रहा था - जैसा कि आप देख सकते हैं, समय-समय पर, एक लाख प्रविष्टियों की सूची के लिए, अतिरिक्त ओवरहेड केवल 0.04 सेकेंड है। और जैसा कि कोरी बताते हैं, पाइथन 3.0 xrange में चलेगा और रेंज आपको वैसे भी अच्छा इटेटरेटर व्यवहार देगा।


रेंज और xrange के बीच अंतर खोजने के लिए इस post को देखें:

उद्धरण के लिए:

range रिटर्न देता है जो आप सोचते हैं: 0. xrange साथ शुरू होने वाली परिभाषित लंबाई के निरंतर पूर्णांक की एक सूची, हालांकि, "xrange ऑब्जेक्ट" लौटाती है , जो एक इटरेटर की तरह एक बड़ा सौदा करती है


रेंज पूरी सूची उत्पन्न करती है और इसे वापस लाती है। xrange नहीं करता - यह मांग पर सूची में संख्या उत्पन्न करता है।


सहायता दस्तावेज़ से।

पायथन 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.

पायथन 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

अंतर स्पष्ट है। पायथन 2.x में, range एक सूची देता है, xrange एक xrange ऑब्जेक्ट देता है जो पुनरावर्तनीय है।

पायथन 3.x में, range पायथन 2.x का xrange बन जाता है, और xrange हटा दिया जाता है।


हर किसी ने इसे काफी समझाया है। लेकिन मैं इसे अपने लिए देखना चाहता था। मैं पायथन 3 का उपयोग करता हूं। इसलिए, मैंने संसाधन मॉनीटर खोला (विंडोज़ में!), और पहले, पहले निम्न आदेश निष्पादित किया गया:

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

और फिर 'उपयोग में' स्मृति में परिवर्तन की जांच की। यह महत्वहीन था। फिर, मैंने निम्नलिखित कोड चलाया:

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

और यह तुरंत उपयोग के लिए स्मृति का एक बड़ा हिस्सा लिया। और, मैं आश्वस्त था। आप इसे अपने लिए आजमा सकते हैं।

यदि आप पाइथन 2 एक्स का उपयोग कर रहे हैं, तो पहले श्रेणी में 'xrange ()' के साथ 'श्रेणी ()' और 'श्रेणी (श्रेणी ())' को 'श्रेणी ()' के साथ बदलें।


xrange केवल रेंज xrange स्टोर करता है और संख्याओं को मांग पर उत्पन्न करता है। हालांकि पाइथन के सी कार्यान्वयन वर्तमान में सी के लंबे समय तक अपने तर्कों को प्रतिबंधित करता है:

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]

ध्यान दें कि पायथन 3.0 में केवल range और यह 2.x xrange तरह व्यवहार करता है लेकिन न्यूनतम और अधिकतम अंत बिंदुओं की सीमाओं के बिना।


रेंज () बनाम xrange () पायथन में:

रेंज () और xrange () दो फ़ंक्शन हैं जिनका उपयोग पाइथन में लूप के लिए एक निश्चित संख्या को फिर से करने के लिए किया जा सकता है। पायथन 3 में, कोई xrange नहीं है, लेकिन रेंज फ़ंक्शन पायथन 2 में xrange जैसा व्यवहार करता है। अगर आप कोड लिखना चाहते हैं जो पाइथन 2 और पायथन 3 दोनों पर चलेंगे, तो आपको श्रेणी () का उपयोग करना चाहिए।

रेंज () - यह रेंज () फ़ंक्शन का उपयोग करके बनाई गई संख्याओं की एक सूची देता है।

xrange () - यह फ़ंक्शन जेनरेटर ऑब्जेक्ट देता है जिसका उपयोग केवल लूपिंग द्वारा संख्याओं को प्रदर्शित करने के लिए किया जा सकता है। मांग पर केवल विशेष सीमा प्रदर्शित होती है और इसलिए "आलसी मूल्यांकन" कहा जाता है।

दोनों अलग-अलग तरीकों से लागू किए गए हैं और उनके साथ जुड़े विभिन्न विशेषताओं हैं। तुलना के अंक हैं:

  1. वापसी प्रकार मेमोरी ऑपरेशन उपयोग गति
  2. याद
  3. ऑपरेशन उपयोग
  4. गति

1. वापसी का प्रकार:

रेंज () रिटर्न - वापसी प्रकार के रूप में सूची।

xrange () रिटर्न - xrange () ऑब्जेक्ट।

# initializing a with range()
a = range(1,10000)

# initializing a with xrange()
x = xrange(1,10000)

# testing the type of a
print ("The return type of range() is : ")
print (type(a))

# testing the type of x
print ("The return type of xrange() is : ")
print (type(x))

आउटपुट:

The return type of range() is :
<type 'list'>
The return type of xrange() is :
<type 'xrange'>

2. मेमोरी:

श्रेणी () द्वारा बनाई गई रेंज को संग्रहीत करने वाला चर xrange () का उपयोग कर रेंज को संग्रहीत चर की तुलना में अधिक मेमोरी लेता है। इसके लिए मूल कारण रिटर्न प्रकार का रेंज () सूची है और xrange () xrange () ऑब्जेक्ट है।

# initializing a with range()
a = range(1,10000)

# initializing a with xrange()
x = xrange(1,10000)

# testing the size of a
print ("The size allotted using range() is : ")
print (sys.getsizeof(a))

# testing the size of a
print ("The size allotted using xrange() is : ")
print (sys.getsizeof(x))

आउटपुट:

The size allotted using range() is : 
80064
The size allotted using xrange() is : 
40

3. संचालन उपयोग:

चूंकि श्रेणी () सूची लौटाती है, सूची में लागू किए जा सकने वाले सभी परिचालनों का उपयोग इस पर किया जा सकता है। दूसरी ओर, जैसे xrange () xrange ऑब्जेक्ट देता है, सूची से जुड़े संचालन उन पर लागू नहीं किए जा सकते हैं, इसलिए एक नुकसान।

# Python code to demonstrate range() vs xrange()
# on  basis of operations usage 

# initializing a with range()
a = range(1,6)

# initializing a with xrange()
x = xrange(1,6)

# testing usage of slice operation on range()
print ("The list after slicing using range is : ")
print (a[2:5])

# testing usage of slice operation on xrange()
print ("The list after slicing using xrange is : ")
print (x[2:5])

आउटपुट:

The list after slicing using range is :
[3, 4, 5]
The list after slicing using xrange is :
Traceback (most recent call last):
  File "pp.py", line 18, in <module>
    print (x[2:5])
TypeError: sequence index must be integer, not 'slice'

4. गति:

इस तथ्य के कारण कि xrange () केवल जनरेटर ऑब्जेक्ट का मूल्यांकन करता है जिसमें आलसी मूल्यांकन द्वारा आवश्यक मूल्य शामिल हैं, इसलिए रेंज () से कार्यान्वयन में तेज़ है।

महत्वपूर्ण बिंदु :

  1. यदि आप कोड लिखना चाहते हैं जो पाइथन 2 और पायथन 3 दोनों पर चलता है, तो रेंज () का उपयोग करें क्योंकि xrange funtion को पायथन 3 में बहिष्कृत किया गया है।
  2. रेंज () एक ही अनुक्रम पर कई बार फिर से चलने पर तेज है।
  3. xrange () को हर बार पूर्णांक ऑब्जेक्ट का पुनर्निर्माण करना होता है, लेकिन रेंज () में वास्तविक पूर्णांक ऑब्जेक्ट्स होंगे। (हालांकि यह स्मृति के मामले में हमेशा खराब प्रदर्शन करेगा)।

Reference


रेंज एक सूची देता है जबकि xrange एक xrange ऑब्जेक्ट देता है जो रेंज आकार के बावजूद एक ही मेमोरी लेता है, इस मामले में, केवल एक तत्व उत्पन्न होता है और प्रति पुनरावृत्ति उपलब्ध होता है जबकि सीमा का उपयोग करने के मामले में, सभी तत्व एक साथ उत्पन्न होते हैं और स्मृति में उपलब्ध हैं।





xrange