पायथन: बाहरी लूप में अगले पुनरावृत्ति के लिए जारी है


135

मैं जानना चाहता था कि क्या अजगर में बाहरी लूप में अगले पुनरावृत्ति को जारी रखने के लिए कोई अंतर्निहित तरीके हैं। उदाहरण के लिए, कोड पर विचार करें:

for ii in range(200):
    for jj in range(200, 400):
        ...block0...
        if something:
            continue
    ...block1...

मैं यह जारी रखना चाहता हूं कि जेज लूप और गोटो अगले आइटम से बाहर निकलने के लिए यह जारी रखें। मैं इस तर्क को किसी अन्य तरीके से (ध्वज चर सेट करके) लागू कर सकता हूं, लेकिन क्या ऐसा करने का एक आसान तरीका है, या क्या यह बहुत अधिक माँगने जैसा है?


11
वास्तव में पायथन के लिए एक कार्यशील गोटो स्टेटमेंट मौजूद है: entrian.com/goto । यह अप्रैल फूल के मज़ाक :-) के रूप में रिलीज़ किया गया था, लेकिन यह काम करने वाला है।
कोडेपे

3
ओह, कृपया कि गोटो मजाक का उपयोग न करें! यह उल्लेखनीय रूप से चतुर है, लेकिन यदि आप इसे अपने कोड में डालते हैं तो आप बाद में दुखी होंगे।
नेड बाचेल्डर

जवाबों:


71
for i in ...:
    for j in ...:
        for k in ...:
            if something:
                # continue loop i

एक सामान्य मामले में, जब आपके पास लूपिंग के कई स्तर होते हैं और breakआपके लिए काम नहीं करता है (क्योंकि आप ऊपरी छोरों में से एक को जारी रखना चाहते हैं, न कि एक के ऊपर एक सही), तो आप निम्न में से एक कर सकते हैं

फ़ंक्शन से बचने के लिए इच्छित लूप को रिफलेक्टर करें

def inner():
    for j in ...:
        for k in ...:
            if something:
                return


for i in ...:
    inner()

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

या आप innerएक नेस्टेड फ़ंक्शन के रूप में परिभाषित कर सकते हैं और इसे बस उस पर कब्जा कर सकते हैं जो इसकी आवश्यकता है (धीमी हो सकती है?)

for i in ...:
    def inner():
        for j in ...:
            for k in ...:
                if something:
                    return
    inner()

अपवादों का उपयोग करें

दार्शनिक रूप से, यह वह है, जब आवश्यक हो, संरचित प्रोग्रामिंग बिल्डिंग ब्लॉकों (यदि, के लिए, जबकि) के माध्यम से कार्यक्रम के प्रवाह को तोड़ दिया जाता है।

लाभ यह है कि आपको कोड के एक टुकड़े को कई भागों में नहीं तोड़ना है। यह अच्छा है अगर यह किसी प्रकार की संगणना है जिसे आप पायथन में लिखते समय डिजाइन कर रहे हैं। इस प्रारंभिक बिंदु पर अमूर्तता का परिचय आपको धीमा कर सकता है।

इस दृष्टिकोण के साथ बुरी बात यह है कि दुभाषिया / संकलक लेखक आमतौर पर यह मानते हैं कि अपवाद असाधारण हैं और तदनुसार उनके लिए अनुकूलन करते हैं।

class ContinueI(Exception):
    pass


continue_i = ContinueI()

for i in ...:
    try:
        for j in ...:
            for k in ...:
                if something:
                    raise continue_i
    except ContinueI:
        continue

इसके लिए एक विशेष अपवाद वर्ग बनाएं, ताकि आप गलती से कुछ अन्य अपवादों को चुप कराने का जोखिम न उठाएं।

पूरी तरह से कुछ और

मुझे यकीन है कि अभी भी अन्य समाधान हैं।


विश्वास नहीं कर सकता कि मैंने अपने दूसरे लूप को दूसरी विधि में ले जाने के बारे में नहीं सोचा। मैं धीमे हो रहा हूं
pmccallum

1
मेरे लिए, अपवाद का उपयोग करना इसे प्राप्त करने का एक अच्छा तरीका है। मैं @ user7610 से सहमत हूं - "दार्शनिक रूप से, यह वह है जो अपवाद हैं"।
रेनैटो बायरो

अच्छा पुराना बूलियन चर और यदि कथन हैं?
मृ।

ओपी उस के लिए एक वैकल्पिक समाधान की तलाश में है, "मैं इस तर्क को किसी अन्य तरीके से लागू कर सकता हूं (एक ध्वज चर सेट करके) [...]"
user7610

149
for ii in range(200):
    for jj in range(200, 400):
        ...block0...
        if something:
            break
    else:
        ...block1...

Break आंतरिक लूप को तोड़ देगा, और ब्लॉक 1 निष्पादित नहीं होगा (यह केवल तभी चलेगा जब आंतरिक लूप सामान्य रूप से बाहर निकलता है)।


1
नमस्ते, क्या इस तरह के कोई अन्य विकल्प हैं? क्योंकि मैं ब्लॉक 1 में लूप के लिए एक और करना चाहता हूं, और इस तरह मेरा कोड 3 स्तर गहरा हो जाएगा। अजीब स्थिति है।
सहस

3
मेरे लिए यह ऐसा लगता है जैसे आप छोरों के लिए कुछ करने की कोशिश कर रहे हैं, जो एक अलग तरीके से सबसे अच्छा होगा ...
किम्विस

हाँ। इसलिए मैंने for..else संरचना का उपयोग नहीं किया। अब मुझे अभी भी लूप की आवश्यकता होगी, लेकिन मैं कंट्रोल को डायवर्ट करने के लिए फ्लैग वेरिएबल का उपयोग करूंगा।
सहस

3
for...elseअक्सर एक उपयोगी निर्माण होता है, हालांकि यह भ्रामक हो सकता है। बस याद रखें कि elseइस संदर्भ में "कोई विराम नहीं"।
asmeurer

यह लूप की सिर्फ दो परतों तक सीमित प्रतीत होता है। मुझे कुछ कोड को अपडेट करने की आवश्यकता है जिसमें तीन नेस्टेड लूप हैं, और एक नई ग्राहक आवश्यकता का मतलब है कि कुछ परिस्थितियों में अंतरतम लूप को बाहरी लूप के अगले पुनरावृत्ति को जारी रखने की आवश्यकता है। मुझे लगता है कि आपका सुझाव उस परिदृश्य पर लागू नहीं होगा।
कास्परड

42

अन्य भाषाओं में आप लूप को लेबल कर सकते हैं और लेबल किए गए लूप से तोड़ सकते हैं। पायथन एन्हांसमेंट प्रपोजल (PEP) 3136 ने इन्हें पायथन में जोड़ने का सुझाव दिया लेकिन गुइडो ने इसे अस्वीकार कर दिया :

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

  1. भाषा में जटिलता स्थायी रूप से जुड़ गई। यह न केवल सभी पायथन कार्यान्वयन को प्रभावित करता है, बल्कि हर स्रोत विश्लेषण उपकरण, प्लस भाषा के सभी पाठ्यक्रम को भी प्रभावित करता है।

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

इसलिए यदि आप भाग्य से बाहर हैं, तो आप यही उम्मीद कर रहे हैं, लेकिन अन्य उत्तरों में से एक को देखें क्योंकि वहाँ अच्छे विकल्प हैं।


4
दिलचस्प। मैं यहां गुइडो से सहमत हूं। जबकि कुछ मामलों के लिए यह अच्छा होगा कि इसका दुरुपयोग किया जाएगा। इसे लागू नहीं करने का एक और कारण यह है कि अभी सी और पायथन के बीच पोर्ट कोड को आगे पीछे करना बहुत आसान है। एक बार जब पायथन ने ऐसी विशेषताएं चुननी शुरू कर दीं, जिनमें अन्य भाषाओं की कमी है तो यह कठिन हो जाता है। उदाहरण के लिए तथ्य यह है कि आप पायथन में पाश के लिए एक और बयान हो सकता है ... यह अन्य भाषाओं के लिए कोड कम पोर्टेबल बनाता है।
eric.frederich

2
ऑल ओएल गुइडो हमारे बीडीएफएल
जेएनब्रायन

4
यह एक अच्छे प्रतिवाद की तुलना में एक लाल-हीरिंग से अधिक है, लेकिन यह मुझे लगता है कि for-elseनामांकित लूप्स की तुलना में व्यवहार अधिक जटिल है, पढ़ने में अधिक कठिन है, और शायद अधिक गाली दी गई है (यदि एक बाहरी गलती नहीं है)। मुझे लगता है कि मैंने एक अलग कीवर्ड का इस्तेमाल किया होगा else- शायद कुछ resumeअच्छा होगा? आप breakपाश में हैं और resumeइसके बाद सही है?
ArtOfWarfare

5
ये मुझे दुखी करता है। मैं विश्वास नहीं कर सकता कि मैं एक ही समय में पायथन से कैसे प्यार और नफरत करता हूं। इतनी खूबसूरत, फिर भी इतनी wtf।
jlh

5
@jlh मेरे लिए ज्यादातर wtf। कभी-कभी मुझे लगता है कि यह वैध उद्देश्य के लिए नहीं बल्कि सिर्फ अलग होने के लिए अलग होना चाहता है। यह इसका एक अच्छा उदाहरण है। मुझे बाहरी छोरों को अक्सर तोड़ने की आवश्यकता होती है।
रिकेलस

14

मुझे लगता है कि आप ऐसा कुछ कर सकते हैं:

for ii in range(200):
    restart = False
    for jj in range(200, 400):
        ...block0...
        if something:
            restart = True
            break
    if restart:
        continue
    ...block1...

4
-1: ओपी ने स्पष्ट रूप से कहा कि वे जानते थे कि वे ऐसा कुछ कर सकते हैं, और यह सिर्फ स्वीकृत उत्तर के एक भयावह संस्करण की तरह दिखता है (जो कि आपके 8 महीने से पहले की भविष्यवाणी करता है, इसलिए ऐसा नहीं हो सकता था कि आप बस स्वीकार कर चुके हैं जवाब)।
ArtOfWarfare

10
स्वीकृत उत्तर स्पष्ट नहीं है यदि आपने पहले कभी नहीं देखा है for, else(और मुझे लगता है कि ज्यादातर लोग जो अपने सिर के शीर्ष को याद नहीं कर सकते हैं कि यह कैसे काम करता है)।
asmeurer

3

मुझे लगता है कि इसे प्राप्त करने के सबसे आसान तरीकों में से एक "विराम" को "विराम" कथन के साथ बदलना है

for ii in range(200):
 for jj in range(200, 400):
    ...block0...
    if something:
        break
 ...block1...       

उदाहरण के लिए, यह देखने के लिए आसान कोड है कि यह वास्तव में कैसे चलता है:

for i in range(10):
    print("doing outer loop")
    print("i=",i)
    for p in range(10):
        print("doing inner loop")
        print("p=",p)
        if p==3:
            print("breaking from inner loop")
            break
    print("doing some code in outer loop")

2

इस तरह की समस्या से निपटने का एक और तरीका है अपवाद () का उपयोग करना।

for ii in range(200):
    try:
        for jj in range(200, 400):
            ...block0...
            if something:
                raise Exception()
    except Exception:
        continue
    ...block1...

उदाहरण के लिए:

for n in range(1,4):
    for m in range(1,4):
        print n,'-',m

परिणाम:

    1-1
    1-2
    1-3
    2-1
    2-2
    2-3
    3-1
    3-2
    3-3

अगर हम m = 3 से बाहरी n लूप में कूदना चाहते हैं, तो मान लें:

for n in range(1,4):
    try:
        for m in range(1,4):
            if m == 3:
                raise Exception()            
            print n,'-',m
    except Exception:
        continue

परिणाम:

    1-1
    1-2
    2-1
    2-2
    3-1
    3-2

संदर्भ लिंक: http://www.programming-idioms.org/idiom/42/continue-outer-loop/1264/pyonon


1

हम कुछ खोजना चाहते हैं और फिर आंतरिक पुनरावृत्ति को रोकना चाहते हैं। मैं एक ध्वज प्रणाली का उपयोग करता हूं।

for l in f:
    flag = True
    for e in r:
        if flag==False:continue
        if somecondition:
            do_something()
            flag=False

मुझे नहीं पता कि आपके समाधान को क्यों ठुकरा दिया गया; किसी ने मूल रूप से एक ही बात पोस्ट की और 10 गुना ऊपर उठ गया
लोकेन डे

मैं stackoverflow के साथ बहुत भाग्यशाली नहीं हूँ।
एस्तेर

1
हो सकता है क्योंकि मूल रूप से वास्तव में एक ही चीज़ यहां पहले से ही पोस्ट की गई है, मुझे लगता है ... और False:continueबात यह है ... असामान्य स्वरूपण। जैसा कि अक्सर "प्राकृतिक" सिस्टम में होता है, जहां घातीय आदर्श होते हैं, आपको केवल महत्वपूर्ण बिंदुओं को प्राप्त करने के लिए SO पर कुछ बार भाग्यशाली होना पड़ता है। वैसे भी, मेरे "सर्वश्रेष्ठ" उत्तर आमतौर पर कम से कम लोकप्रिय हैं।
user7610

0

मैंने बस कुछ ऐसा किया है। इसके लिए मेरा समाधान एक सूची समझ के साथ लूप के लिए इंटीरियर को बदलना था।

for ii in range(200):
    done = any([op(ii, jj) for jj in range(200, 400)])
    ...block0...
    if done:
        continue
    ...block1...

जहां ऑप कुछ बूलियन ऑपरेटर ii और jj के संयोजन पर अभिनय कर रहा है। मेरे मामले में, यदि कोई भी ऑपरेशन सही हुआ, तो मुझे किया गया।

यह वास्तव में एक फ़ंक्शन में कोड को तोड़ने से अलग नहीं है, लेकिन मैंने सोचा कि "किसी भी" ऑपरेटर का उपयोग तार्किक या बुलियन की सूची में करने के लिए और सभी को एक पंक्ति में करना दिलचस्प था। यह फ़ंक्शन कॉल से भी बचता है।

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