रेंज (स्टार्ट, एंड) में एंड क्यों शामिल नहीं है?


305
>>> range(1,11)

आपको देता है

[1,2,3,4,5,6,7,8,9,10]

1-11 क्यों नहीं?

क्या उन्होंने इसे ठीक उसी तरह से करने का फैसला किया है या इसका कुछ मूल्य है जो मैं नहीं देख रहा हूं?


11
दिज्कस्ट्रा, ewd831
साइलेंटगॉस्ट

11
मूल रूप से आप दूसरे के लिए एक-एक बग ऑफ-बाय का एक सेट चुन रहे हैं। एक सेट के कारण आपके छोरों के जल्दी समाप्त होने की संभावना होती है, दूसरे में अपवाद (या अन्य भाषाओं में बफर अतिप्रवाह) होने की संभावना होती है। एक बार जब आप कोड का एक गुच्छा लिख ​​लेंगे, तो आप देखेंगे कि व्यवहार range()का विकल्प बहुत अधिक बार समझ में आता है
जॉन ला रूय

32
Dijkstra, ewd831 से लिंक करें: cs.utexas.edu/users/EWD/ewd08xx/EWD831.PDF
unutbu

35
@unutbu वह Djikstra लेख इस विषय में अक्सर उद्धृत किया गया है, लेकिन यहां कुछ भी मूल्य नहीं है, लोग इसे केवल अधिकार की अपील के रूप में उपयोग करते हैं। केवल प्रासंगिक छद्म कारण वह ओपी के प्रश्न के लिए देता है वह यह महसूस करता है कि ऊपरी सीमा सहित "अप्राकृतिक" और "बदसूरत" हो जाता है विशेष मामले में जहां अनुक्रम खाली है - यह पूरी तरह से व्यक्तिपरक स्थिति है और आसानी से खिलाफ बहस करता है। तो यह मेज पर ज्यादा नहीं लाता है। मेसा के साथ "प्रयोग" उनके विशेष बाधाओं या मूल्यांकन विधियों को जाने बिना बहुत अधिक मूल्य का नहीं है।
सूंदर -

6
@andreasdr लेकिन भले ही कॉस्मेटिक तर्क मान्य हो, क्या पायथन का दृष्टिकोण पठनीयता की एक नई समस्या का परिचय नहीं देता है? सामान्य उपयोग अंग्रेजी में "रेंज" शब्द का अर्थ है कि कुछ कुछ से कुछ तक होता है - जैसे एक अंतराल। वह लेन (सूची (रेंज (1,2))) 1 रिटर्न और लेन (सूची (2))) रिटर्न 2 ऐसी चीज है जिसे आपको वास्तव में पचाना सीखना है।
आर्मिन

जवाबों:


245

क्योंकि यह कॉल करने के लिए अधिक सामान्य है कि range(0, 10)कौन से रिटर्न [0,1,2,3,4,5,6,7,8,9]में 10 तत्व हैं जो बराबर हैं len(range(0, 10))। याद रखें कि प्रोग्रामर 0-आधारित इंडेक्सिंग पसंद करते हैं।

इसके अलावा, निम्नलिखित सामान्य कोड स्निपेट पर विचार करें:

for i in range(len(li)):
    pass

क्या आप देख सकते हैं कि अगर यह range()ठीक है len(li)कि यह समस्याग्रस्त हो जाएगा? प्रोग्रामर को स्पष्ट रूप से घटाने की आवश्यकता होगी। यह प्रोग्रामर की सामान्य प्रवृत्ति को भी पसंद for(int i = 0; i < 10; i++)करता है for(int i = 0; i <= 9; i++)

यदि आप बार-बार 1 की सीमा के साथ कॉल कर रहे हैं, तो आप अपने स्वयं के कार्य को परिभाषित करना चाह सकते हैं:

>>> def range1(start, end):
...     return range(start, end+1)
...
>>> range1(1, 10)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

48
अगर यही तर्क होता तो पैरामीटर नहीं होते range(start, count)?
मार्क रैनसम

3
@ शोगुन प्रारंभ मान डिफॉल्ट 0 पर है, यानी range(10)के बराबर है range(0, 10)
मोइनुद्दीन

4
आपका range1उन श्रेणियों के साथ काम नहीं करेगा जिनके पास एक अलग चरण आकार है 1
dimo414

6
आप बताते हैं कि रेंज (x) 0 से शुरू होनी चाहिए और x "रेंज की लंबाई" होगी। ठीक। लेकिन आपने यह नहीं बताया कि क्यों रेंज (x, y) को x से शुरू होना चाहिए और y-1 के साथ समाप्त होना चाहिए। यदि प्रोग्रामर 1 से 3 तक के साथ एक फॉर-लूप चाहता है, तो उसे स्पष्ट रूप से जोड़ना होगा 1. क्या यह वास्तव में सुविधा के बारे में है?
आर्मिन

7
for i in range(len(li)):बल्कि एक एंटीपैटर्न है। एक का उपयोग करना चाहिए enumerate
हंस

27

यद्यपि यहां कुछ उपयोगी एल्गोरिथम स्पष्टीकरण हैं, मुझे लगता है कि यह कुछ सरल 'वास्तविक जीवन' को जोड़ने में मदद कर सकता है क्योंकि यह इस तरह से काम करता है, जिसे मैंने युवा नवागंतुकों के लिए विषय को पेश करते समय उपयोगी पाया है:

'रेंज (1,10)' जैसी किसी चीज के साथ यह सोचकर भ्रम पैदा हो सकता है कि मापदंडों का जोड़ा "आरंभ और अंत" का प्रतिनिधित्व करता है।

यह वास्तव में प्रारंभ और "स्टॉप" है।

अब, अगर यह थे "अंत" मूल्य तो, हाँ, आप उम्मीद कर सकते है कि संख्या के अनुक्रम में अंतिम प्रविष्टि के रूप में शामिल किया जाएगा। लेकिन यह "अंत" नहीं है।

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

तो मुख्य बिंदु इसका नाम याद रखना है: " स्टॉप "। इसका मतलब है कि यह वह बिंदु है जिस पर पहुंचने पर, पुनरावृत्ति तुरंत बंद हो जाएगी। उस बिंदु के बाद नहीं ।

इसलिए, जबकि "स्टार्ट" वास्तव में शामिल होने के पहले "स्टॉप" वैल्यू को 'ब्रेक' तक पहुंचाने पर 'वैल्यू' को शामिल करने का प्रतिनिधित्व करता है, जबकि स्टॉप करने से पहले 'उस एक और साथ ही' को प्रोसेस करना जारी रहता है।

एक सादृश्य जो मैंने बच्चों को यह समझाने में इस्तेमाल किया है, वह है, विडंबना यह है कि यह बच्चों की तुलना में बेहतर व्यवहार है! यह माना जाता है के बाद बंद नहीं करता है - यह तुरंत खत्म हो जाता है बिना यह खत्म कर रहा है कि यह क्या कर रहा था। (वे इसे प्राप्त करते हैं;))

एक और सादृश्य - जब आप एक कार ड्राइव आप नहीं है पारित एक को रोकने / उपज / 'दे जिस तरह से' चिह्न और इसे कहीं के बगल में अपनी कार में बैठे, या पीछे, साथ खत्म। जब आप रोकते हैं तो तकनीकी रूप से आप अभी भी उस तक नहीं पहुंचे हैं। यह 'उन चीजों में शामिल नहीं है जिन्हें आप अपनी यात्रा में पारित कर चुके हैं'।

मुझे आशा है कि उनमें से कुछ Pythonitos / Pythonitas को समझाने में मदद करता है!


यह स्पष्टीकरण अधिक सहज है। धन्यवाद
फ्रेड

बच्चों की व्याख्या सिर्फ उल्लसित है!
एंटनी हैचकिंस

1
तुम एक सुअर पर लिपस्टिक लगाने की कोशिश कर रहे हो। "स्टॉप" और "एंड" के बीच का अंतर बेतुका है। यदि मैं 1 से 7 तक जाता हूं, तो मैं 7 से पास नहीं हुआ हूं। यह केवल पायथन का एक दोष है, जिसमें शुरुआत और ठहराव के लिए अलग-अलग सम्मेलन हैं। मानव सहित अन्य भाषाओं में, "एक्स से वाई तक" का अर्थ "एक्स से वाई तक" है। पायथन में, "X: Y" का अर्थ "X: Y-1" है। यदि आपकी बैठक 9 से 11 के बीच है, तो क्या आप लोगों को बताते हैं कि यह 9 से 12 या 8 से 11 तक है?
bzip2

24

विशेष श्रेणी के कुछ लाभ हैं:

एक चीज के लिए प्रत्येक आइटम range(0,n)लंबाई की सूचियों के लिए एक वैध सूचकांक है n

की range(0,n)लंबाई भी है n, n+1जो एक समावेशी सीमा नहीं होगी।


18

यह शून्य-आधारित अनुक्रमण के साथ संयोजन में अच्छी तरह से काम करता है और len()। उदाहरण के लिए, यदि आपके पास किसी सूची में 10 आइटम xहैं, तो उनकी संख्या 0-9 है। range(len(x))आपको 0-9 देता है।

बेशक, लोग आपको बताएंगे कि यह करने के बजाय for item in xया अधिक पायथोनिक for index, item in enumerate(x)है for i in range(len(x))

स्लाइसिंग उस तरह से भी काम करता है: foo[1:4]1-3 में से आइटम है foo(यह ध्यान में रखते हुए कि आइटम 1 वास्तव में शून्य-आधारित अनुक्रमणिका के कारण दूसरा आइटम है)। स्थिरता के लिए, उन्हें दोनों एक ही तरह से काम करना चाहिए।

मैं इसके बारे में सोचता हूं: "पहला नंबर जिसे आप चाहते हैं, उसके बाद पहला नंबर जिसे आप नहीं चाहते हैं।" यदि आप 1-10 चाहते हैं, तो पहली संख्या जो आप नहीं चाहते हैं वह 11 है, इसलिए यह है range(1, 11)

यदि यह किसी विशेष एप्लिकेशन में बोझिल हो जाता है, तो यह थोड़ा आसान है कि यह एक सहायक फ़ंक्शन लिखता है जो एंडिंग इंडेक्स में 1 जोड़ता है और कॉल करता है range()


1
टुकड़ा करने पर सहमत। w = 'abc'; w[:] == w[0:len(w)]; w[:-1] == w[0:len(w)-1];
केवपी

def full_range(start,stop): return range(start,stop+1) ## helper function
नोबार

शायद for index, item in enumerate(x)भ्रम से बचने के लिए
गूढ़

@ सीन धन्यवाद, निश्चित।
किंडल

12

यह बंटवारे श्रेणियों के लिए भी उपयोगी है; range(a,b)में विभाजित किया जा सकता है range(a, x)और range(x, b), जबकि समावेशी रेंज के साथ आप या तो लिखते थे x-1या x+1। जब आपको शायद ही कभी श्रेणियों को विभाजित करने की आवश्यकता होती है, तो आप बहुत बार सूचियों को विभाजित करते हैं, जो कि सूची को खंगालने के कारणों में से एक है, जिसमें l[a:b]ए-थ तत्व शामिल है, लेकिन बी-वें नहीं। फिर rangeएक ही संपत्ति होने से यह अच्छी तरह से सुसंगत हो जाता है।


11

सीमा की लंबाई शीर्ष मान शून्य से नीचे का मान है।

यह बहुत कुछ के समान है:

for (var i = 1; i < 11; i++) {
    //i goes from 1 to 10 in here
}

एक सी शैली की भाषा में।

रूबी की रेंज भी पसंद है:

1...11 #this is a range from 1 to 10

हालांकि, रूबी मानती है कि कई बार आप टर्मिनल वैल्यू को शामिल करना चाहते हैं और वैकल्पिक सिंटैक्स प्रदान करते हैं:

1..10 #this is also a range from 1 to 10

17
गाह! मैं रूबी का उपयोग नहीं करते हैं, लेकिन मैं कल्पना कर सकते हैं कि 1..10बनाम 1...10जब कोड को पढ़ने के बीच अंतर करना मुश्किल जा रहा है!
मोइनुद्दीन

6
@marcog - जब आप दो रूपों को जानते हैं तो आपकी आँखें अंतर के साथ
उपस्थित होती हैं

11
रूबी की रेंज ऑपरेटर पूरी तरह से सहज है। लंबे समय तक फॉर्म आपको छोटा क्रम देता है। खांसी
रसेल बोरोगोव

4
@ रसेल, शायद 1 ............ 20 को 1..10 जैसी रेंज देनी चाहिए। अब इसके लिए स्विच करने लायक चीनी की कुछ मात्रा होगी। ;)
केवपी

4
@ रसेल अतिरिक्त बिंदु सीमा से बाहर अंतिम आइटम को
निचोड़ता है

5

मूल रूप से अजगर में range(n)iterates nबार, विशेष स्वभाव है यही कारण है कि यह अंतिम मान नहीं देता है जब यह मुद्रित किया जा रहा है, हम एक समारोह जो समावेशी मूल्य तो इसका मतलब यह भी अंतिम मान रेंज में उल्लेख प्रिंट होगा देता है बना सकते हैं की है।

def main():
    for i in inclusive_range(25):
        print(i, sep=" ")


def inclusive_range(*args):
    numargs = len(args)
    if numargs == 0:
        raise TypeError("you need to write at least a value")
    elif numargs == 1:
        stop = args[0]
        start = 0
        step = 1
    elif numargs == 2:
        (start, stop) = args
        step = 1
    elif numargs == 3:
        (start, stop, step) = args
    else:
        raise TypeError("Inclusive range was expected at most 3 arguments,got {}".format(numargs))
    i = start
    while i <= stop:
        yield i
        i += step


if __name__ == "__main__":
    main()

4

कोड पर विचार करें

for i in range(10):
    print "You'll see this 10 times", i

विचार यह है कि आपको लंबाई की एक सूची मिलती है y-x, जिसे आप (जैसा कि आप ऊपर देखते हैं) से अधिक पुनरावृति कर सकते हैं।

श्रेणी के लिए अजगर डॉक्स पर पढ़ें - वे प्राथमिक usecase के लिए लूप पुनरावृत्ति पर विचार करते हैं।


1

यह कई मामलों में तर्क करने के लिए अधिक सुविधाजनक है।

असल में, हम एक सीमा के बीच के अंतराल के रूप में सोच सकते हैं startऔर end। यदि start <= end, उनके बीच के अंतराल की लंबाई है end - start। यदि lenवास्तव में लंबाई के रूप में परिभाषित किया गया था, तो आपके पास होगा:

len(range(start, end)) == start - end

हालांकि, हम अंतराल की लंबाई को मापने के बजाय सीमा में शामिल पूर्णांकों की गणना करते हैं। उपरोक्त संपत्ति को सही रखने के लिए, हमें समापन बिंदुओं में से एक को शामिल करना चाहिए और दूसरे को बाहर करना चाहिए।

stepपैरामीटर जोड़ना लंबाई की एक इकाई शुरू करने जैसा है। उस स्थिति में, आप अपेक्षा करेंगे

len(range(start, end, step)) == (start - end) / step

लंबाई के लिए। गिनती प्राप्त करने के लिए, आप केवल पूर्णांक विभाजन का उपयोग करते हैं।


पायथन की असंगतता के ये बचाव प्रफुल्लित करने वाले हैं। अगर मुझे दो संख्याओं के बीच अंतराल चाहिए था, तो मैं अंतराल के बजाय अंतर प्राप्त करने के लिए घटाव का उपयोग क्यों करूंगा? यह आरंभ और अंत पदों के लिए विभिन्न अनुक्रमण सम्मेलनों का उपयोग करने के लिए असंगत है। 5 से 21 स्थान पाने के लिए आपको "5:22" लिखने की आवश्यकता क्यों होगी?
bzip2

यह अजगर का नहीं है, यह बोर्ड भर में बहुत आम है। सी, जावा, रूबी में, आप इसे नाम देते हैं
आर्सेनी

मेरा कहने का मतलब है कि यह अनुक्रमण के लिए सामान्य है, ऐसा नहीं है कि अन्य भाषाओं में एक ही तरह की सटीक वस्तु है
Arseny
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.