Python3 में कोई xrange फंक्शन क्यों नहीं है?


273

हाल ही में मैंने Python3 का उपयोग करना शुरू किया और यह xrange हर्ट्स की कमी है।

सरल उदाहरण:

1) पायथन 2:

from time import time as t
def count():
  st = t()
  [x for x in xrange(10000000) if x%4 == 0]
  et = t()
  print et-st
count()

2) पायथन 3:

from time import time as t

def xrange(x):

    return iter(range(x))

def count():
    st = t()
    [x for x in xrange(10000000) if x%4 == 0]
    et = t()
    print (et-st)
count()

परिणाम क्रमशः हैं:

1) 1.53888392448 2) 3.215819835662842

ऐसा क्यों है? मेरा मतलब है, क्यों xrange को हटा दिया गया है? यह सीखने के लिए एक महान उपकरण है। शुरुआती लोगों के लिए, खुद की तरह, जैसे हम सभी किसी बिंदु पर थे। इसे क्यों हटाएं? क्या कोई मुझे उचित पीईपी की ओर इशारा कर सकता है, मैं इसे नहीं ढूंढ सकता।

चीयर्स।


231
rangeपायथन में 3.x xrangeपायथन 2.x से है। यह वास्तव में पायथन 2.x rangeथा जिसे हटा दिया गया था।
औरोव

27
पुनश्च, आपको कभी भी समय नहीं देना चाहिए time। उपयोग करने में आसान होने के अलावा और गलत होने के लिए कठिन है, और आपके लिए परीक्षण दोहराते हुए, timeitउन सभी प्रकार की चीजों का ध्यान रखता है जिन्हें आप याद नहीं करेंगे, या यहां तक ​​कि कैसे, देखभाल करने के लिए (जैसे जीसी को अक्षम करना), और उपयोग कर सकते हैं हजारों बार बेहतर संकल्प के साथ घड़ी।
22'13

7
इसके अलावा, तुम क्यों समय फिल्टर करने के लिए परीक्षण कर रहे हैं rangeपर x%4 == 0? क्यों सिर्फ परीक्षण list(xrange())बनाम list(range()), इसलिए वहाँ है संभव के रूप में छोटे से बाहरी काम के रूप में? (उदाहरण के लिए, आप कैसे जानते हैं। 3.x x%4अधिक धीमी गति से नहीं कर रहा है ?) उस मामले के लिए, आप एक विशाल क्यों बना रहे हैं list, जिसमें संपूर्ण मेमोरी आवंटन शामिल है (जो धीमा होने के अलावा, अविश्वसनीय रूप से परिवर्तनशील भी है) ?
गर्भपात

5
देखें docs.python.org/3.0/whatsnew/3.0.html ) "सीमा (अब, xrange () व्यवहार करने के लिए इस्तेमाल की तरह बर्ताव को छोड़कर यह मनमाने ढंग से आकार के मूल्यों के साथ काम करता है उत्तरार्द्ध:, अनुभाग" दृश्य और Iterators इसके बजाय सूचियों में से "। अब मौजूद नहीं है।" तो, रेंज अब एक पुनरावृत्ति देता है। iter(range)बेमानी है।
टूलमेकरसेव

9
क्षमा करें, परिवर्तन डॉक्टर को उद्धृत करते हुए एहसास हुआ कि यह स्पष्ट रूप से स्पष्ट नहीं है। किसी और के लिए जो उलझन में है, और लंबे समय से स्वीकृत उत्तर के माध्यम से पढ़ना नहीं चाहता है, और उसकी सभी टिप्पणियाँ: जहाँ भी आप अजगर 2 में xrange का उपयोग कर रहे थे, अजगर में रेंज का उपयोग करें 3. यह वही करता है जो xrange करते थे, जो है एक पुनरावृत्ति करने वाला। यदि आपको किसी सूची में परिणाम चाहिए, तो करें list(range(..))। यह अजगर 2 की रेंज के बराबर है। या इसे दूसरे तरीके से कहें: xrange का नाम बदल दिया गया है, क्योंकि यह बेहतर डिफ़ॉल्ट है; list(range)यदि आपके पास वास्तव में सूची की आवश्यकता है , तो दोनों को करना आवश्यक नहीं था ।
टूलमेकर

जवाबों:


175

कुछ प्रदर्शन माप, का उपयोग कर timeit इसके बजाय मैन्युअल रूप से करने की कोशिश करने के बजाय time

सबसे पहले, Apple 2.7.2 64-बिट:

In [37]: %timeit collections.deque((x for x in xrange(10000000) if x%4 == 0), maxlen=0)
1 loops, best of 3: 1.05 s per loop

अब, python.org 3.3.0 64-बिट:

In [83]: %timeit collections.deque((x for x in range(10000000) if x%4 == 0), maxlen=0)
1 loops, best of 3: 1.32 s per loop

In [84]: %timeit collections.deque((x for x in xrange(10000000) if x%4 == 0), maxlen=0)
1 loops, best of 3: 1.31 s per loop

In [85]: %timeit collections.deque((x for x in iter(range(10000000)) if x%4 == 0), maxlen=0) 
1 loops, best of 3: 1.33 s per loop

जाहिरा तौर पर, 3.x range वास्तव में 2.x की तुलना में थोड़ा धीमा है xrange। और ओपी के xrangeकार्य का इससे कोई लेना-देना नहीं है। (आश्चर्य की बात नहीं, क्योंकि __iter__स्लॉट में एक बार कॉल करने की संभावना लूप में जो कुछ भी होता है, 10000000 कॉल के बीच दिखाई नहीं देता है, लेकिन किसी ने इसे एक संभावना के रूप में लाया है।)

लेकिन यह केवल 30% धीमा है। ओपी को धीमी गति से 2x कैसे मिला? ठीक है, अगर मैं 32-बिट पायथन के साथ एक ही परीक्षण दोहराता हूं, तो मुझे 1.58 बनाम 3.12 मिलता है। तो मेरा अनुमान है कि यह अभी तक उन मामलों में से एक है जहां 3.x को 32-बिट को चोट पहुंचाने वाले तरीकों से 64-बिट प्रदर्शन के लिए अनुकूलित किया गया है।

लेकिन क्या वाकई इससे फर्क पड़ता है? 3.3.0 64-बिट के साथ इसे फिर से देखें:

In [86]: %timeit [x for x in range(10000000) if x%4 == 0]
1 loops, best of 3: 3.65 s per loop

इसलिए, निर्माण list संपूर्ण पुनरावृत्ति की तुलना में दोगुना से अधिक होता है।

और जैसा कि "मेरे परीक्षण से पायथन 2.6+" की तुलना में बहुत अधिक संसाधनों का उपभोग करता है, यह 3.x जैसा दिखता है range जैसा बिल्कुल के समान आकार का है xrange, भले ही यह 10x जितना बड़ा हो, अनावश्यक सूची का निर्माण करना अभी भी 10000000x के बारे में एक समस्या से कुछ भी अधिक है कि सीमा पुनरावृत्ति संभवतः कर सकती है।

और forअंदर सी लूप के बजाय एक स्पष्ट लूप के बारे में क्या deque?

In [87]: def consume(x):
   ....:     for i in x:
   ....:         pass
In [88]: %timeit consume(x for x in range(10000000) if x%4 == 0)
1 loops, best of 3: 1.85 s per loop

तो, लगभग समय के रूप में ज्यादा समय बर्बाद किया for बयान कि पुनरावृति के वास्तविक कार्य में range

यदि आप किसी श्रेणी ऑब्जेक्ट के पुनरावृत्ति को अनुकूलित करने के बारे में चिंतित हैं, तो आप शायद गलत जगह देख रहे हैं।


इस बीच, आप पूछते रहते हैं कि क्यों xrangeहटाया गया, चाहे कितनी ही बार लोग आपसे एक ही बात कहें, लेकिन मैं इसे फिर से दोहराऊंगा: इसे हटाया नहीं गया: इसका नाम बदलकर range2.x कर दिया गया ।range को हटा दिया गया।

यहाँ कुछ प्रमाण है कि 3.3 rangeऑब्जेक्ट 2.x xrangeऑब्जेक्ट का प्रत्यक्ष वंशज है (और 2.x rangeफ़ंक्शन का नहीं): 3.3range और 2.7xrange का स्रोत । तुम भी बदल इतिहास देख सकते हैं (लिंक से जुड़ा हुआ, मेरा मानना ​​है कि, वह परिवर्तन जो स्ट्रिंग के अंतिम उदाहरण "फ़ाइल में कहीं भी हो" को बदल सकते हैं)।

तो, यह धीमा क्यों है?

खैर, एक के लिए, उन्होंने बहुत सारी नई सुविधाएँ जोड़ी हैं। दूसरे के लिए, उन्होंने सभी जगह (विशेषकर पुनरावृति के अंदर) सभी प्रकार के परिवर्तन किए हैं जिनके छोटे दुष्प्रभाव हैं। और विभिन्न महत्वपूर्ण मामलों को नाटकीय रूप से अनुकूलित करने के लिए बहुत सारे काम थे, भले ही यह कभी-कभी कम महत्वपूर्ण मामलों को थोड़ा कम कर देता है। यह सब जोड़ें, और मुझे आश्चर्य नहीं है कि rangeजितना संभव हो उतना तेज़ चलना अब थोड़ा धीमा है। यह उन कम महत्वपूर्ण मामलों में से एक है जिन पर ध्यान केंद्रित करने के लिए कोई भी कभी भी पर्याप्त देखभाल नहीं करेगा। किसी को भी कभी भी वास्तविक जीवन में उपयोग होने की संभावना नहीं होती है जहां यह प्रदर्शन अंतर उनके कोड में हॉटस्पॉट होता है।


लेकिन यह केवल 30% धीमा है। अभी भी धीमी है, लेकिन एक महान प्रतिक्रिया दोस्त, के बारे में सोचने के लिए कुछ। हालांकि यह मेरे प्रश्न का उत्तर नहीं देता है: xrange को क्यों हटाया गया था ?? इसके बारे में इस तरह से सोचें - यदि आपके पास मल्टीप्रोसेसिंग के आधार पर एक प्रदर्शन-आश्रित ऐप है, तो यह जानने के लिए कि एक समय का उपभोग करने के लिए आपको कितनी कतार की आवश्यकता है, 30% फर्क पड़ेगा या नहीं? आप देखते हैं, आप कहते हैं कि यह कोई फर्क नहीं पड़ता, लेकिन हर बार जब मैं रेंज का उपयोग करता हूं तो मुझे लगता है कि विशाल व्यथित प्रशंसक ध्वनि का अर्थ है कि यह सबसे खराब है, जबकि xrange यह नहीं करता है। इसके बारे में सोचें;)
उत्प्रेरित

9
@ कैटालेसिया: एक बार फिर, इसे हटाया नहीं गया, इसे सिर्फ नाम दिया गया rangerange3.3 में वस्तु के एक प्रत्यक्ष वंशज है xrangeकी नहीं, 2.7 में वस्तु range2.7 में कार्य करते हैं। यह पूछने के समान है जबकि itertools.imapइसके पक्ष में हटा दिया गया था map। कोई उत्तर नहीं है, क्योंकि ऐसी कोई बात नहीं हुई।
22'13

1
@ कटैलिसिया: मामूली प्रदर्शन परिवर्तन संभवत: श्रेणियों को धीमा करने के लिए एक प्रत्यक्ष डिजाइन निर्णय का परिणाम नहीं है, लेकिन पायथन के सभी परिवर्तनों के 4 वर्षों के साइड इफेक्ट ने कई चीजें तेज कर दी हैं, कुछ चीजें थोड़ी धीमी (और कुछ चीजें) x86_64 पर तेज़ लेकिन x86 पर धीमा, या कुछ उपयोग के मामलों में तेज़ लेकिन दूसरों में धीमा) आदि। किसी को भी 30% अंतर के बारे में किसी भी तरह से चिंतित होने की संभावना नहीं थी कि किसी rangeऔर चीज को करने में कितना समय लगता है।
अबार्नेट

1
"किसी को भी 30% अंतर के बारे में किसी भी तरह से चिंतित होने की संभावना नहीं थी कि किसी और चीज को करते समय एक सीमा को पुनरावृत्त करने में कितना समय लगता है "
उत्प्रेरक

18
@ कटलेसिया: हां, बिल्कुल। लेकिन आपको लगता है कि इसका मतलब है कि यह जो कहता है उसके विपरीत है। यह उपयोग का मामला नहीं है कि कोई भी कभी भी परवाह करेगा, इसलिए किसी ने ध्यान नहीं दिया कि यह 30% धीमा है। तो क्या? यदि आप एक वास्तविक जीवन कार्यक्रम पा सकते हैं जो कि पायथन 3.3 में 2.7 (या 2.6) की तुलना में धीरे-धीरे चलता है, तो लोग इसकी देखभाल करेंगे। यदि आप नहीं कर सकते, तो वे नहीं करेंगे, और आपको भी नहीं करना चाहिए।
अब्राह्मण

141

पायथन 3 की रेंज है को Python2 के xrange। इसके चारों ओर एक पुनरावृति लपेटने की आवश्यकता नहीं है। पायथन 3 में एक वास्तविक सूची प्राप्त करने के लिए, आपको उपयोग करने की आवश्यकता हैlist(range(...))

यदि आप ऐसा कुछ चाहते हैं जो Python2 और Python3 के साथ काम करता है, तो यह प्रयास करें

try:
    xrange
except NameError:
    xrange = range

1
कभी-कभी आपको कोड की आवश्यकता होती है जो पायथन 2 और 3 दोनों में काम करता है। यह एक अच्छा समाधान है।
ग्रेग ग्लेंकर

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

आप इस परियोजना से xrange का उपयोग कर सकते हैं। नहीं है futurize: उपकरण के लिए स्वचालित रूप से आप स्रोत कोड परिवर्तित python-future.org/...
guettli

17

अजगर 3 का range प्रकार Python 2 की तरह ही काम करता है xrange। मुझे यकीन नहीं है कि आप एक मंदी क्यों देख रहे हैं, क्योंकि इट्रेटर आपके xrangeफ़ंक्शन द्वारा लौटाया गया है, वही है जो आपको rangeसीधे मिलने पर होता है।

मैं अपने सिस्टम पर मंदी को पुन: उत्पन्न करने में सक्षम नहीं हूं। यहाँ मैंने परीक्षण किया है:

अजगर 2, के साथ xrange :

Python 2.7.3 (default, Apr 10 2012, 23:24:47) [MSC v.1500 64 bit (AMD64)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> import timeit
>>> timeit.timeit("[x for x in xrange(1000000) if x%4]",number=100)
18.631936646865853

पायथन 3, के साथ range एक छोटा सा तेज है:

Python 3.3.0 (v3.3.0:bd8afb90ebf2, Sep 29 2012, 10:57:17) [MSC v.1600 64 bit (AMD64)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> import timeit
>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=100)
17.31399508687869

मुझे हाल ही में पता चला कि पायथन 3 के rangeप्रकार में कुछ अन्य साफ-सुथरी विशेषताएं हैं, जैसे कि स्लाइसिंग के लिए समर्थन: range(10,100,2)[5:25:5]है range(20, 60, 10)!


शायद मंदी xrangeइतनी बार नए की तलाश से आती है , या कि केवल एक बार किया जाता है?
Askewchan

क्या वास्तव में एक पुनरावृत्ति गति को बढ़ाता है? मैंने सोचा कि यह सिर्फ स्मृति को बचाया।
पूछना

3
@catalesia मुझे लगता है कि यहां मुद्दा यह है कि है xrangeथा नहीं , हटाया सिर्फ नाम बदला
पूछने

1
@ ब्लैंकैन्थ: चीयर्स, लेकिन यह अभी भी एक स्पष्टीकरण पसंद करता है: "सेट शाब्दिक और समझ [19] [20] [किया] {x} का अर्थ है सेट ([x]); x, y} का अर्थ है सेट ([) x, y])। {S में P के लिए x (F) के लिए {F (x)} का अर्थ है यदि S (P) (x) में x के लिए सेट (F (x)) तो NB। {श्रेणी (x)} का अर्थ है सेट (। [रेंज (x)]), सेट नहीं (रेंज (x))। खाली सेट के लिए कोई शाब्दिक नहीं है; उपयोग सेट () (या {1} & {2} :-); कोई फ्रोजेनसेट शाब्दिक नहीं है; वे भी हैं शायद ही कभी जरूरत
पड़े

3
3.x में सबसे बड़ी जीत range, जहां तक ​​मेरा सवाल है, निरंतर-समय है __contains__। न्यूबॉइक्स लिखते थे 300000 in xrange(1000000)और इस वजह से यह पूरे xrange(या कम से कम पहले 30%) को पुनरावृत्त करता था, इसलिए हमें यह समझाना पड़ा कि यह एक बुरा विचार क्यों था, भले ही यह बहुत ही आकर्षक लगता हो। अब, यह है pythonic।
22'13

1

अपने python2 कोड को ठीक करने का एक तरीका है:

import sys

if sys.version_info >= (3, 0):
    def xrange(*args, **kwargs):
        return iter(range(*args, **kwargs))

1
बिंदु python3 में है xrange को परिभाषित नहीं किया गया है, इसलिए विरासत कोड जिसने xrange को तोड़ दिया।
andrew pate

नहीं, बस परिभाषित करें range = xrangeजैसा कि @John La Roy
mimi.vx

@ mimi.vx सुनिश्चित नहीं है कि रेंज = xrange Python3 में काम करेगा क्योंकि xrange परिभाषित नहीं है। मेरी टिप्पणी उस मामले को संदर्भित करती है, जहां आपके पास पुरानी विरासत कोड है जिसमें xrange कॉल हैं और इसे python3 के तहत चलाने के लिए इसे प्राप्त करने की कोशिश कर रहे हैं।
एंड्रयू पाट

1
आह, मेरा बुरा .. xrange = range... मैंने बयानों को बदल दिया
mimi.vx

रेंज है एक iiterator, और वैसे भी यह एक भयानक विचार भले ही यह नहीं था होगा क्योंकि यह पहली संपूर्ण रेंज खोल करना पड़ता है और बात की इस तरह के लिए एक iterator उपयोग करने के लाभों खो देता है। तो सही प्रतिक्रिया नहीं है "रेंज = xrange" इसकी "xrange = रेंज"
Shayne

0

पायथन 2 से xrange एक जनरेटर है और इटरेटर को लागू करता है जबकि रेंज केवल एक फ़ंक्शन है। Python3 में मुझे नहीं पता कि xrange को क्यों छोड़ा गया।


नहीं, रेंज इंटरएटर नहीं है। आप इस संरचना के साथ अगला () नहीं कर सकते। अधिक जानकारी के लिए, आप यहाँ देख सकते हैं treyhunner.com/2018/02/python-range-is-not-an-iterator
मिशेल फर्नांडीस

स्पष्टीकरण के लिए बहुत बहुत धन्यवाद। लेकिन मैं मूल टिप्पणी के इरादे को बहाल करूंगा, और वह यह है कि पीवाई 3 पीवाई 2 range()के बराबर है xrange()। और इस प्रकार PY3 xrange()निरर्थक है।
स्टीफन राउच

-2

COMP: ~ $ अजगर अजगर 2.7.6 (डिफ़ॉल्ट, Jun 22 2015, 17:58:13) linux2 पर [जीसीसी 4.8.2]

>>> import timeit
>>> timeit.timeit("[x for x in xrange(1000000) if x%4]",number=100)

5.656799077987671

>>> timeit.timeit("[x for x in xrange(1000000) if x%4]",number=100)

5.579368829727173

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=100)

21.54827117919922

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=100)

22.014557123184204

समय संख्या के साथ = 1 परम:

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=1)

0.2245171070098877

>>> timeit.timeit("[x for x in xrange(1000000) if x%4]",number=1)

.10750913619995117

comp: ~ $ python3 Python 3.4.3 (डिफ़ॉल्ट, 14 अक्टूबर 2015, 20:28:29) [GCC 4.8.4] लिनक्स पर

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=100)

9.113872020003328

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=100)

9.07014398300089

समय के साथ संख्या = 1,2,3,4 परम त्वरित और रैखिक तरीके से काम करता है:

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=1)

.09329321900440846

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=2)

.18501482300052885

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=3)

0.2703447980020428

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=4)

.36209142999723554

तो ऐसा लगता है कि अगर हम timeit.timeit (1% रेंज में x (1000000) में x% 4] ", संख्या = 1) (जैसा कि हम वास्तव में वास्तविक कोड में उपयोग करते हैं) की तरह 1 रनिंग लूप चक्र को मापते हैं। लेकिन दोहराया छोरों में अजगर 2 xrange () अजगर 3 से रेंज () के खिलाफ गति में जीतता है।


लेकिन यह भाषा द्वारा ही है ... xrange / रेंज से कोई लेना देना नहीं है।
mimi.vx
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.