कैसे कई छोरों को तोड़ने के लिए?


479

निम्नलिखित कोड को देखते हुए (जो काम नहीं करता है):

while True:
    #snip: print out current state
    while True:
        ok = get_input("Is this ok? (y/n)")
        if ok.lower() == "y": break 2 #this doesn't work :(
        if ok.lower() == "n": break
    #do more processing with menus and stuff

क्या यह काम करने का कोई तरीका है? या क्या मेरे पास इनपुट लूप से बाहर निकलने के लिए एक चेक है, तो एक और, अधिक सीमित, बाहरी लूप में चेक करें कि क्या उपयोगकर्ता संतुष्ट है?


87
क्यों नहीं पायथन में सिर्फ 'ब्रेक (एन)' है जहां n उन स्तरों की संख्या है जहां से आप तोड़ना चाहते हैं।
नाथन

2
C ++ यहाँ अच्छा है gotoयदि आप बहुत सारे छोरों में गहरे बसे हुए हैं
ड्रेक जॉनसन

जवाबों:


512

मेरी पहली वृत्ति नेस्टेड लूप को एक फ़ंक्शन में रिफलेक्टर करने और returnबाहर तोड़ने के लिए उपयोग करना होगा।


3
यह एक और विचार है जो मेरे पास था, क्योंकि get_input_yn () फ़ंक्शन कहीं और उपयोगी होगा, मुझे यकीन है।
मैथ्यू शारले

96
इस विशिष्ट मामले में सहमति व्यक्त की गई, लेकिन 'मेरे पास नेस्टेड लूप्स हैं, के सामान्य मामले में मैं क्या करूं' रिफैक्टरिंग का कोई मतलब नहीं हो सकता है।
quick_dry

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

5
आमतौर पर आंतरिक लूप को अपनी विधि में फिर से भरना संभव है, जो बाहरी लूप को तोड़ने के लिए झूठे जारी रखने के लिए सही है। जबकि condition1: / यदि MyLoop2 (params) नहीं: विराम। एक विकल्प एक बूलीयन ध्वज स्थापित करना है, जिसका परीक्षण दोनों स्तरों पर किया जाता है। अधिक = सत्य / जबकि कंडिशन 1 और अधिक: / जबकि कंडीशन 2 और अधिक: / यदि स्टॉपकंडिशन: अधिक = गलत / विराम / ...
टूलमेकर

7
मैं सहमत हूं कि उपयोग करने का प्रयास returnसही दृष्टिकोण है। और तर्क यह है कि, पायथन के ज़ेन के अनुसार , "फ्लैट नेस्टेड से बेहतर है"। हमारे यहां तीन स्तर के घोंसले के शिकार हैं और अगर वह रास्ते में आना शुरू हो जाता है, तो घोंसले को कम करने या कम से कम पूरे घोंसले को अपने स्वयं के कार्य में निकालने का समय है।
लुत्ज प्रेचल

239

यहाँ एक और तरीका है जो छोटा है। नुकसान यह है कि आप केवल बाहरी लूप को तोड़ सकते हैं, लेकिन कभी-कभी यह वही है जो आप चाहते हैं।

for a in xrange(10):
    for b in xrange(20):
        if something(a, b):
            # Break the inner loop...
            break
    else:
        # Continue if the inner loop wasn't broken.
        continue
    # Inner loop was broken, break the outer.
    break

इस के लिए / अन्यथा निर्माण का उपयोग करता है: क्यों और बाद में छोरों के लिए अजगर 'और' का उपयोग क्यों करता है?

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

continueबयान जादू यहाँ है। यह दूसरे के क्लाज में है। अगर कोई आंतरिक विराम नहीं है तो परिभाषा के अनुसार । उस स्थिति में continueबड़े करीने से बाहरी विराम की परिधि होती है।


6
@eugeney क्यों नहीं? पहला ब्रेक भीतरी लूप से बाहर निकलेगा।
नवीन

5
@eugeney मुझे लगता है कि मैं यहाँ कुछ याद कर रहा हूँ। क्या आप एक उदाहरण पोस्ट कर सकते हैं?
नवीन

4
@Mingliang जारी रखने से पहले जा सकते हैं।
बाल्ड्रिक k

1
एक रेमंड हेटिंगर वीडियो, youtu.be/OSGv2VnC0go?t=971 से प्राप्त करें , "no_break" के रूप में लूप के लिए संलग्न "और" कथनों को पढ़ें, फिर समझना आसान हो जाता है।
अंबरीश

2
यह चतुर है। :-) हालाँकि, सीधे-सीधे नहीं। सच कहूँ तो, मैं पायथन से बाहर लेबल तोड़ने या तोड़ने (एन) को रखने के लिए तर्कों से आश्वस्त नहीं हूं। वर्कअराउंड अधिक जटिलता जोड़ते हैं।
rfportilla

148

पीईपी 3136 लेबल विच्छेद / जारी रखने का प्रस्ताव करता है। गुइडो ने इसे अस्वीकार कर दिया क्योंकि "इस सुविधा की आवश्यकता के लिए कोड बहुत जटिल है" बहुत दुर्लभ है। पीईपी कुछ वर्कअराउंड्स का उल्लेख करता है, हालांकि (जैसे अपवाद तकनीक), जबकि गुइडो को लगता है कि रिटर्न का उपयोग करने के लिए ज्यादातर मामलों में वापसी सरल होगी।


73
हालाँकि, रिफ्लेक्टर / returnआमतौर पर जाने का रास्ता है, मैंने काफी कुछ ऐसे मामले देखे हैं जहाँ एक सरल संक्षिप्त ' break 2' कथन सिर्फ इतना ही समझ में आता है। इसके अलावा, रिफ्लेक्टर / के returnलिए समान काम नहीं करता है continue। इन मामलों में, सांख्यिक विराम और जारी रखने के लिए एक छोटे से कार्य को फिर से शुरू करने और अपवादों को कम करने के लिए, या प्रत्येक घोंसले के स्तर पर एक ध्वज को स्थापित करने से जुड़े तर्क को शामिल करने की तुलना में कम बरबाद करना आसान होगा। यह शर्म की बात है कि गुइडो ने इसे खारिज कर दिया।
जेम्स हाई

10
break; breakअच्छा होगा।
प्युर्लेज़

5
@Jeyekomon समस्या यह है कि आपको समस्या होने के लिए 3 या अधिक नेस्टेड छोरों की आवश्यकता नहीं है। 2 नेस्टेड लूप्स बहुत आम हैं
जॉन

6
"इस सुविधा की आवश्यकता के लिए कोड बहुत जटिल है" बहुत दुर्लभ है। लेकिन यदि आप कभी भी इस कोड का उपयोग करते हैं, तो लेबल वाले छोरों की कमी इसे और भी जटिल बना देगी, क्योंकि आपको breakसभी छोरों के माध्यम से मैन्युअल रूप से आगे बढ़ना चाहिए । बेवकूफ।
बॉलपॉइंटबैन

3
जाहिरा तौर पर, मैं केवल 5 मिनट के लिए एक पोस्ट संपादित कर सकता हूं (यह 6 हो गया है)। तो, यहाँ मेरी संपादित पोस्ट है: मेरे 2 सेंट: पर्ल ने विराम को लेबल किया है (लेकिन इसे 'अंतिम' कहते हैं) और 'अगले' को सीधे अगले पुनरावृत्ति पर ले जाने के लिए। यह बिल्कुल दुर्लभ नहीं है - मैं हर समय इसका उपयोग करता हूं। मैं अजगर के लिए बिल्कुल नया हूं और पहले से ही इसके लिए एक आवश्यकता है। इसके अलावा, गिने जाने वाले ब्रेक रिफैक्टरिंग के लिए भयानक होंगे - लूप को लेबल करने के लिए बेहतर है जिसे आप बाहर निकालना चाहते हैं, फिर स्पष्ट रूप से यह बताने के लिए कि आप किस लूप से बाहर निकलना चाहते हैं, ब्रेक <लेबल> का उपयोग करें।
जॉन दीघन

119

पहला, साधारण तर्क सहायक होता है।

यदि, किसी कारण के लिए, समाप्त करने वाली शर्तों पर काम नहीं किया जा सकता है, तो अपवाद एक पतन-वापस योजना है।

class GetOutOfLoop( Exception ):
    pass

try:
    done= False
    while not done:
        isok= False
        while not (done or isok):
            ok = get_input("Is this ok? (y/n)")
            if ok in ("y", "Y") or ok in ("n", "N") : 
                done= True # probably better
                raise GetOutOfLoop
        # other stuff
except GetOutOfLoop:
    pass

इस विशिष्ट उदाहरण के लिए, एक अपवाद आवश्यक नहीं हो सकता है।

दूसरी ओर, हमारे पास अक्सर चरित्र-मोड अनुप्रयोगों में "वाई", "एन" और "क्यू" विकल्प होते हैं। "क्यू" विकल्प के लिए, हम तत्काल बाहर निकलना चाहते हैं। यह अधिक असाधारण है।


4
गंभीरता से, अपवाद बेहद सस्ते हैं और मुहावरेदार अजगर बहुत सारे और उनमें से कई का उपयोग करता है। कस्टम लोगों को परिभाषित करना और फेंकना बहुत आसान है, साथ ही साथ।
ग्रेग लिंड

13
दिलचस्प विचार। मैं उससे प्यार करने या उससे नफरत करने के लिए फट गया हूं।
क्रेग मैकक्वीन

8
यह समाधान अधिक सहायक होगा, यदि यह दो भिन्नताओं को अलग-अलग दिखाता है। (१) ध्वज का उपयोग करना ( done)। (२) अपवाद उठाना। उन्हें एक ही समाधान में एक साथ विलय करना जटिल बनाता है। भविष्य के पाठकों के लिए: EITHER इसमें शामिल सभी पंक्तियों का उपयोग करता है done, या परिभाषित करता है GetOutOfLoop(Exception)और इसके अलावा / बढ़ाता है।
टूलमेकरवेट

4
सामान्य तौर पर, किसी भी चीज़ के लिए कोशिश करने वाले ब्लॉक का उपयोग करना और फिर अपवादों पर बहुत ध्यान दिया जाता है। कोशिश-ब्लॉक विशेष रूप से त्रुटि से निपटने के लिए डिज़ाइन किए गए हैं, और कुछ अजीब नियंत्रण प्रवाह के लिए उनका उपयोग करना बहुत अच्छा नहीं है, स्टाइलिस्टिक रूप से।
नोबिलीग्रीन

2
पायथन 3 में यह raise Exception('GetOutOfLoop')और होगा except Exception:
tommy.carstensen

54

मैं इस बात से सहमत हूं कि इस प्रकार की स्थिति के लिए एक फ़ंक्शन में रिफैक्टिंग करना आमतौर पर सबसे अच्छा तरीका है, लेकिन जब आपको वास्तव में नेस्टेड छोरों से बाहर निकलने की आवश्यकता होती है, तो यहां @ S.Lott का अपवाद-अपवाद दृष्टिकोण का एक दिलचस्प संस्करण है। यह withअपवाद बढ़ाने के लिए पायथन के कथन का उपयोग करता है जो थोड़ा सा अच्छा लगता है। एक नए संदर्भ प्रबंधक को परिभाषित करें (आपको केवल एक बार ऐसा करना होगा):

from contextlib import contextmanager
@contextmanager
def nested_break():
    class NestedBreakException(Exception):
        pass
    try:
        yield NestedBreakException
    except NestedBreakException:
        pass

अब आप इस संदर्भ प्रबंधक का उपयोग इस प्रकार कर सकते हैं:

with nested_break() as mylabel:
    while True:
        print "current state"
        while True:
            ok = raw_input("Is this ok? (y/n)")
            if ok == "y" or ok == "Y": raise mylabel
            if ok == "n" or ok == "N": break
        print "more processing"

लाभ: (1) यह थोड़ा साफ है (कोई स्पष्ट प्रयास-सिवाय ब्लॉक के), और (2) आपको Exceptionप्रत्येक उपयोग के लिए एक कस्टम-निर्मित उपवर्ग प्राप्त होता है nested_break; Exceptionहर बार अपने स्वयं के उपवर्ग को घोषित करने की आवश्यकता नहीं है ।


40

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

आप निम्न तरीके से गोटो का उपयोग भी कर सकते हैं (अप्रैल फूल मॉड्यूल का उपयोग यहां से ):

#import the stuff
from goto import goto, label

while True:
    #snip: print out current state
    while True:
        ok = get_input("Is this ok? (y/n)")
        if ok == "y" or ok == "Y": goto .breakall
        if ok == "n" or ok == "N": break
    #do more processing with menus and stuff
label .breakall

मुझे पता है, मुझे पता है, "आप गोटो का उपयोग नहीं करेंगे" और वह सब, लेकिन यह इस तरह के अजीब मामलों में अच्छी तरह से काम करता है।


1
अगर यह INTERCAL में COME FROM कमांड की तरह है, तो कुछ भी नहीं
1800 INFORMATION

3
मुझे मजाक पसंद है, लेकिन स्टैक ओवरफ्लो की बात अच्छे कोड को बढ़ावा देने के लिए है, इसलिए मुझे आपको नीचे वोट देना होगा :(
क्रिस्चियन अवार्ड

13
मुझे लगता है कि अच्छे कोड के रूप में योग्य होने के लिए यह एक साफ और पठनीय पर्याप्त समाधान है, इसलिए मैं इसे वोट करता हूं। :)
जेटी हर्ले

1
@JTHurley नहीं यह साफ और पठनीय नहीं है। मेरा मतलब है, ऐसा लग सकता है कि यह इस उदाहरण में साफ और पठनीय है , लेकिन किसी भी वास्तविक जीवन परिदृश्य में गोटो एक पवित्र गड़बड़ है । (इसके अलावा यह sooo विरोधी pythonic है ...)
एलो महाल

2
गोटो एक बुरा प्रतिनिधि हो जाता है, किसी भी पेशेवर कोडर को मेरी राय में इसे ठीक से संभालने में सक्षम होना चाहिए।
अल्बर्ट रेनशॉ

33

एक नए चर का परिचय दें जिसका उपयोग आप 'लूप ब्रेकर' के रूप में करेंगे। पहले इसे कुछ (असाइन करें, 0, आदि) असाइन करें, और फिर, बाहरी लूप के अंदर, इससे पहले कि आप इसे से तोड़ दें, मान को कुछ और में बदल दें (सत्य, 1, ...)। एक बार जब लूप बाहर निकलता है तो उस मान के लिए 'पैरेंट' लूप की जाँच करें। मुझे प्रदर्शित करें:

breaker = False #our mighty loop exiter!
while True:
    while True:
        if conditionMet:
            #insert code here...
            breaker = True 
            break
    if breaker: # the interesting part!
        break   # <--- !

यदि आपके पास एक अनंत लूप है, तो यह एकमात्र तरीका है; अन्य छोरों के निष्पादन के लिए वास्तव में बहुत तेज है। यह भी काम करता है यदि आपके पास कई नेस्टेड लूप हैं। आप सभी से बाहर निकल सकते हैं, या बस कुछ कर सकते हैं। अंतहीन संभावनाए! उम्मीद है कि इस मदद की!


22

कई नेस्टेड छोरों को तोड़ने के लिए, एक फ़ंक्शन में रिफैक्ट किए बिना, अंतर्निहित स्टॉपइंटरेशन अपवाद के साथ "नकली गोटो स्टेटमेंट" का उपयोग करें :

try:
    for outer in range(100):
        for inner in range(100):
            if break_early():
                raise StopIteration

except StopIteration: pass

नेस्टेड लूप से बाहर निकलने के लिए गोटो स्टेटमेंट के उपयोग पर इस चर्चा को देखें ।


1
यह अपवाद को संभालने के लिए अपनी खुद की कक्षा बनाने की तुलना में बहुत अच्छा लगता है, और बहुत साफ दिखता है। क्या ऐसा कोई कारण है जो मुझे नहीं करना चाहिए?
21

वास्तव में StopIteration जनरेटर के लिए उपयोग कर रहा है, लेकिन मुझे लगता है कि आम तौर पर आपके पास कोई भी अप्रतिबंधित StopIteration अपवाद नहीं है। तो यह एक अच्छा समाधान की तरह लगता है, लेकिन नए अपवाद बनाने में कोई गलती नहीं है।
कोवलस्की

1
मेरे लिए सबसे अच्छा और सरल उपाय
अलेक्जेंड्रे हुआट

16

keeplooping=True
while keeplooping:
    #Do Stuff
    while keeplooping:
          #do some other stuff
          if finisheddoingstuff(): keeplooping=False

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


यह ध्वज की स्थापना की तरह है!
SIslam

मुझे लगता है कि यह एक बहुत अच्छा समाधान है।
कोवलस्की

13

यह ऐसा करने का सबसे अच्छा तरीका नहीं है, लेकिन मेरी राय में, यह सबसे अच्छा तरीका है।

def loop():
    while True:
    #snip: print out current state
        while True:
            ok = get_input("Is this ok? (y/n)")
            if ok == "y" or ok == "Y": return
            if ok == "n" or ok == "N": break
        #do more processing with menus and stuff

मुझे पूरा यकीन है कि आप यहां भी पुनरावृत्ति का उपयोग करके कुछ काम कर सकते हैं, लेकिन मुझे पता है कि अगर आपके लिए यह एक अच्छा विकल्प है।


यह मेरे लिए सही समाधान था। मेरा उपयोग मामला ओपी के मुकाबले बहुत अलग था। मैं क्रमपरिवर्तन खोजने के लिए अनिवार्य रूप से एक ही डेटा पर दो बार लूपिंग कर रहा था, इसलिए मैं दो छोरों को अलग नहीं करना चाहता था।
ब्रायन पीटरसन

9

और अगर दो स्थितियाँ सत्य हैं तो लूपिंग को क्यों नहीं रखा जाए? मुझे लगता है कि यह एक अधिक पैथोनिक तरीका है:

dejaVu = True

while dejaVu:
    while True:
        ok = raw_input("Is this ok? (y/n)")
        if ok == "y" or ok == "Y" or ok == "n" or ok == "N":
            dejaVu = False
            break

है ना?

शुभकामनाएं।


सिर्फ क्यों नहीं while dejaVu:? आप इसे वैसे भी सच पर सेट करें।
मैथ्यू शारले

काम करता है कि अरे! मैं Trueदो छोरों को छोड़ने के लिए दो स्थितियों में सोच रहा था , लेकिन सिर्फ एक ही काफी है।
मौरो एस्पे

2
@MatthewScharley मुझे लगता है कि यह दिखाना है कि यह नेस्टेड लूप में काम करता है।
संभाल

@ MauroAspé यह ठीक नहीं होगा जो ओपी अनुरोध करता है। यह अभी भी पूरे बाहरी लूप को निष्पादित करेगा, लेकिन लक्ष्य यह है कि यदि आप बाकी कोड तोड़ते हैं तो निष्पादन नहीं होगा
यम

@ यम if not dejaVu: breakनीचे से हल नहीं किया जा सकता है और इस प्रकार मुख्य लूप से बाहर निकल सकता है? मुझे लगता है कि जो पूछा गया था उसका समाधान सबसे करीब है। +1
मिल्क सेप

8

फैक्टर में अपने लूप लॉजिक को फैक्टर करें जो लूप वेरिएबल्स की पैदावार करता है और जब किया जाता है तो रिटर्न करता है - यहाँ एक सरल एक है जो पंक्तियों / कॉलमों में इमेजेस देता है जब तक कि हम इमेजेस से बाहर या उन्हें लगाने के लिए जगहों से बाहर न हों:

def it(rows, cols, images):
    i = 0
    for r in xrange(rows):
        for c in xrange(cols):
            if i >= len(images):
                return
            yield r, c, images[i]
            i += 1 

for r, c, image in it(rows=4, cols=4, images=['a.jpg', 'b.jpg', 'c.jpg']):
    ... do something with r, c, image ...

यह जटिल लूप तर्क और प्रसंस्करण को विभाजित करने का लाभ है ...


3

इस मामले में, जैसा कि दूसरों द्वारा भी बताया गया है, कार्यात्मक अपघटन जाने का रास्ता है। पायथन 3 में कोड:

def user_confirms():
    while True:
        answer = input("Is this OK? (y/n) ").strip().lower()
        if answer in "yn":
            return answer == "y"

def main():
    while True:
        # do stuff
        if user_confirms():
            break

3

पायथन while ... elseसंरचना में एक छिपी हुई चाल है जिसका उपयोग ज्यादा कोड परिवर्तन / परिवर्धन के बिना डबल ब्रेक का अनुकरण करने के लिए किया जा सकता है। संक्षेप में यदि whileस्थिति झूठी है, तो elseब्लॉक चालू हो जाता है। न तो अपवाद हैं, continueया ब्लॉक को breakट्रिगर करें else। अधिक जानकारी के लिए " बयान करते समय अजगर पर Else क्लॉज ", या Python doc ऑन (v2.7) के उत्तर देखें

while True:
    #snip: print out current state
    ok = ""
    while ok != "y" and ok != "n":
        ok = get_input("Is this ok? (y/n)")
        if ok == "n" or ok == "N":
            break    # Breaks out of inner loop, skipping else

    else:
        break        # Breaks out of outer loop

    #do more processing with menus and stuff

केवल नकारात्मक पक्ष यह है कि आपको डबल ब्रेकिंग कंडीशन को स्थिति में स्थानांतरित करने की आवश्यकता है while(या एक ध्वज चर जोड़ें)। इस प्रकार की भिन्नताएं forलूप के लिए भी मौजूद होती हैं , जहां elseलूप पूरा होने के बाद ब्लॉक को ट्रिगर किया जाता है।


यह डबल ब्रेक की आवश्यकता को पूरा नहीं करता है। सटीक दी गई समस्या के लिए काम करता है, लेकिन वास्तविक प्रश्न के लिए नहीं।
डेकरॉन

@Dakkaron क्या आप सुनिश्चित हैं कि आपने कोड को सही ढंग से समझा है? कोड वास्तव में OPs प्रश्न को हल करता है, और अनुरोध के समान टूट जाता है। हालांकि यह कई छोरों से बाहर नहीं निकलता है, लेकिन ब्रेक को दोगुना करने की आवश्यकता को बदलने के लिए किसी अन्य खंड का उपयोग करता है।
होलोर ५'१६

मेरी समझ से प्रश्न था How to break out of multiple loops in Python?और उत्तर "यह काम नहीं करता है, कुछ और प्रयास करें" होना चाहिए था । मुझे पता है कि यह ओपी के सटीक उदाहरण को ठीक करता है, लेकिन उनके सवाल का जवाब नहीं देता है।
डाककर्ण

@Dakkaron, कोड के तहत समस्या विवरण देखें, और मेरी राय में यह वास्तव में OPs प्रश्न का उत्तर देता है।
होलीरॉय

2

एक एकल-स्तरीय लूप में अपने पुनरावृत्ति को कम करने का दूसरा तरीका जनरेटर के उपयोग के माध्यम से होगा जैसा कि अजगर संदर्भ में भी निर्दिष्ट है

for i, j in ((i, j) for i in A for j in B):
    print(i , j)
    if (some_condition):
        break

आप इसे लूप के लिए किसी भी स्तर तक ले सकते हैं

नकारात्मक पक्ष यह है कि अब आप केवल एक ही स्तर को नहीं तोड़ सकते। यह सब या कुछ भी नहीं है।

एक और नकारात्मक पक्ष यह है कि यह थोड़ी देर के लूप के साथ काम नहीं करता है। मैं मूल रूप से अजगर पर यह जवाब पोस्ट करना चाहता था - `ब्रेक` सभी छोरों से बाहर है लेकिन दुर्भाग्य से यह इस के डुप्लिकेट के रूप में बंद है


1
यह काम करता है जबकि छोरों के लिए भी, आपको केवल अपने जनरेटर को एक दोष (उपज के साथ) के रूप में लिखना होगा, न कि एक समझ के रूप में।
वेकी

हाँ, एक PyCon में एक वक्ता यहाँ दावा करता है कि यहां तक ​​कि @ RobertRossney का स्वीकृत उत्तर वास्तव में Pythonic नहीं है, लेकिन एक जनरेटर कई छोरों को तोड़ने का सही तरीका है। (मैं पूरा वीडियो देखने की सलाह
दूंगा

2

यहाँ आने का मेरा कारण यह है कि मेरे पास एक बाहरी लूप और एक आंतरिक लूप था जैसे:

for x in array:
  for y in dont_use_these_values:
    if x.value==y:
      array.remove(x)  # fixed, was array.pop(x) in my original answer
      continue

  do some other stuff with x

जैसा कि आप देख सकते हैं, यह वास्तव में अगले x पर नहीं जाएगा, लेकिन इसके बजाय अगले y पर जाएगा।

जो मैंने इसे हल करने के लिए पाया, वह इसके बजाय दो बार सरणी के माध्यम से चलना था:

for x in array:
  for y in dont_use_these_values:
    if x.value==y:
      array.remove(x)  # fixed, was array.pop(x) in my original answer
      continue

for x in array:
  do some other stuff with x

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


यह शायद पायथन नहीं है। सरणी का प्रकार क्या है? शायद सूची, लेकिन इसमें क्या शामिल है? यहां तक ​​कि अगर इसमें इन्ट्स हैं, तो array.pop (x) संभवतः वह नहीं करेगा जो आप चाहते हैं।
17

ये एक अच्छा बिंदु है। मुझे वह कोड नहीं मिला जिसे मैंने संदर्भित किया था। इसे पढ़ने वाले किसी भी व्यक्ति के लिए, array.pop (i) "सरणी से आइटम को सरणी से हटाता है और इसे वापस करता है।" अजगर प्रलेखन के अनुसार। इसलिए किसी को इस कोड को अपेक्षित रूप से कार्य करने के लिए सरणी में आइटम x का सूचकांक प्राप्त करने की आवश्यकता होगी। Array.remove (x) फ़ंक्शन भी है जो वह करेगा जो अपेक्षित है। मैं उस त्रुटि को ठीक करने के लिए अपने उत्तर को ऊपर संशोधित करूंगा। यह मानता है कि दूसरे सरणी में कोई डुप्लिकेट नहीं है, क्योंकि array.remove (x) केवल x के पहले उदाहरण को हटा देगा।
नाथन गारबेडियन

ठीक है, तो मैं समझ गया। उस मामले में, बस के breakबजाय का उपयोग कर continueआप क्या चाहते हैं, यह नहीं होगा? :-)
वेकी

हाँ, दक्षता और स्पष्टता के लिए, आप शायद इन उदाहरणों में जारी रखने के बजाय ब्रेक का उपयोग करना चाहते हैं। :)
नाथन गारबेडियन

2

एक अनंत जनरेटर का उपयोग करने का प्रयास करें।

from itertools import repeat
inputs = (get_input("Is this ok? (y/n)") for _ in repeat(None))
response = (i.lower()=="y" for i in inputs if i.lower() in ("y", "n"))

while True:
    #snip: print out current state
    if next(response):
        break
    #do more processing with menus and stuff

2

एक समारोह का उपयोग करके:

def myloop():
    for i in range(1,6,1):  # 1st loop
        print('i:',i)
        for j in range(1,11,2):  # 2nd loop
            print('   i, j:' ,i, j)
            for k in range(1,21,4):  # 3rd loop
                print('      i,j,k:', i,j,k)
                if i%3==0 and j%3==0 and k%3==0:
                    return  # getting out of all loops

myloop()

साथ ही ऊपर टिप्पणी करके उपरोक्त कोड चलाने का प्रयास करें return

किसी भी फ़ंक्शन का उपयोग किए बिना:

done = False
for i in range(1,6,1):  # 1st loop
    print('i:', i)
    for j in range(1,11,2):  # 2nd loop
        print('   i, j:' ,i, j)
        for k in range(1,21,4):  # 3rd loop
            print('      i,j,k:', i,j,k)
            if i%3==0 and j%3==0 and k%3==0:
                done = True
                break  # breaking from 3rd loop
        if done: break # breaking from 2nd loop
    if done: break     # breaking from 1st loop

अब, उपरोक्त कोड पहले की तरह चलाएं और फिर breakनीचे से एक बार में प्रत्येक पंक्ति को एक-एक करके टिप्पणी करके चलाने का प्रयास करें ।


2

एकल, ब्रेक करने योग्य लूप में कई छोरों को चालू करने का एक आसान तरीका उपयोग करना है numpy.ndindex

for i in range(n):
  for j in range(n):
    val = x[i, j]
    break # still inside the outer loop!

for i, j in np.ndindex(n, n):
  val = x[i, j]
  break # you left the only loop there was!

आपको अपनी वस्तुओं में अनुक्रमित करना होगा, क्योंकि स्पष्ट रूप से मूल्यों के माध्यम से पुनरावृत्ति करने में सक्षम होने का विरोध किया जाता है, लेकिन कम से कम सरल मामलों में यह सुझाए गए अधिकांश उत्तरों की तुलना में लगभग 2-20 गुना अधिक सरल लगता है।


2
# this version uses a level counter to choose how far to break out

break_levels = 0
while True:
    # snip: print out current state
    while True:
        ok = get_input("Is this ok? (y/n)")
        if ok == "y" or ok == "Y":
            break_levels = 1        # how far nested, excluding this break
            break
        if ok == "n" or ok == "N":
            break                   # normal break
    if break_levels:
        break_levels -= 1
        break                       # pop another level
if break_levels:
    break_levels -= 1
    break

# ...and so on

1

नीचे की तरह शायद बहुत कम चाल है अगर समारोह में refactorial पसंद नहीं करेंगे

लूप की स्थिति को नियंत्रित करने के लिए 1 ब्रेक_वेल चर जोड़ा गया

break_level = 0
# while break_level < 3: # if we have another level of nested loop here
while break_level < 2:
    #snip: print out current state
    while break_level < 1:
        ok = get_input("Is this ok? (y/n)")
        if ok == "y" or ok == "Y": break_level = 2 # break 2 level
        if ok == "n" or ok == "N": break_level = 1 # break 1 level

1

आप एक चर (उदाहरण के लिए break_statement ) को परिभाषित कर सकते हैं , फिर दो-ब्रेक की स्थिति होने पर इसे एक अलग मान में बदल सकते हैं और यदि दूसरे लूप से भी तोड़ने के लिए इसे स्टेटमेंट में उपयोग कर सकते हैं।

while True:
    break_statement=0
    while True:
        ok = raw_input("Is this ok? (y/n)")
        if ok == "n" or ok == "N": 
            break
        if ok == "y" or ok == "Y": 
            break_statement=1
            break
    if break_statement==1:
        break

अच्छी बात है, हालांकि हमारे आंतरिक स्तर से ऊपर के प्रत्येक स्तर में हमें उस चर को स्कैन करना होगा। वास्तव में बुरा लगता है कि भाषा में GoTo निर्देश, प्रदर्शन-वार नहीं है।
अनातोली अलेक्सेव

1

मैं आपको याद दिलाना चाहता हूं कि पायथन में फ़ंक्शन को कोड के ठीक बीच में बनाया जा सकता है और आसपास के चर को पढ़ने के लिए और लेखन के लिए nonlocalया globalघोषणा के साथ पारदर्शी रूप से एक्सेस किया जा सकता है ।

तो आप किसी फ़ंक्शन को "ब्रेक करने योग्य नियंत्रण संरचना" के रूप में उपयोग कर सकते हैं, उस स्थान को परिभाषित करते हुए जिसे आप वापस करना चाहते हैं:

def is_prime(number):

    foo = bar = number

    def return_here():
        nonlocal foo, bar
        init_bar = bar
        while foo > 0:
            bar = init_bar
            while bar >= foo:
                if foo*bar == number:
                    return
                bar -= 1
            foo -= 1

    return_here()

    if foo == 1:
        print(number, 'is prime')
    else:
        print(number, '=', bar, '*', foo)

>>> is_prime(67)
67 is prime
>>> is_prime(117)
117 = 13 * 9
>>> is_prime(16)
16 = 4 * 4

1

2 तरीकों में समाधान

एक उदाहरण के साथ: क्या ये दोनों मैट्रीस समान / समान हैं?
मैट्रिक्स 1 और मैट्रिक्स 2 समान आकार, एन, 2 डायमेंशनल मैट्रीस हैं।

पहला समाधान , एक समारोह के बिना

same_matrices = True
inner_loop_broken_once = False
n = len(matrix1)

for i in range(n):
    for j in range(n):

        if matrix1[i][j] != matrix2[i][j]:
            same_matrices = False
            inner_loop_broken_once = True
            break

    if inner_loop_broken_once:
        break

एक समारोह के साथ दूसरा समाधान ,
यह मेरे मामले का अंतिम समाधान है

def are_two_matrices_the_same (matrix1, matrix2):
    n = len(matrix1)
    for i in range(n):
        for j in range(n):
            if matrix1[i][j] != matrix2[i][j]:
                return False
    return True

आपका दिन शुभ हो!


1
# this version breaks up to a certain label

break_label = None
while True:
    # snip: print out current state
    while True:
        ok = get_input("Is this ok? (y/n)")
        if ok == "y" or ok == "Y":
            break_label = "outer"   # specify label to break to
            break
        if ok == "n" or ok == "N":
            break
    if break_label:
        if break_label != "inner":
            break                   # propagate up
        break_label = None          # we have arrived!
if break_label:
    if break_label != "outer":
        break                       # propagate up
    break_label = None              # we have arrived!

#do more processing with menus and stuff

0

उम्मीद है कि यह मदद करता है:

x = True
y = True
while x == True:
    while y == True:
         ok = get_input("Is this ok? (y/n)") 
         if ok == "y" or ok == "Y":
             x,y = False,False #breaks from both loops
         if ok == "n" or ok == "N": 
             break #breaks from just one

0

यहाँ एक कार्यान्वयन है जो काम करता है:

break_ = False
for i in range(10):
    if break_:
        break
    for j in range(10):
        if j == 3:
            break_ = True
            break
        else:
            print(i, j)

एकमात्र ड्रा बैक यह है कि आपको break_छोरों से पहले परिभाषित करना होगा ।


0

भाषा स्तर से ऐसा करने का कोई तरीका नहीं है। कुछ भाषाओं में गोटो होता है, दूसरों को एक विराम लगता है जो एक तर्क लेता है, अजगर नहीं करता है।

सबसे अच्छे विकल्प हैं:

  1. एक ध्वज सेट करें जिसे बाहरी लूप द्वारा जांचा जाता है, या बाहरी छोरों की स्थिति सेट करें।

  2. लूप को एक फंक्शन में रखें और एक ही बार में सभी लूप्स को तोड़ने के लिए रिटर्न का उपयोग करें।

  3. अपने तर्क को सुधारें।

इसका श्रेय 1987 से विवेक नागराजन, प्रोग्रामर को जाता है


फ़ंक्शन का उपयोग करना

def doMywork(data):
    for i in data:
       for e in i:
         return 

झंडे का उपयोग करना

is_break = False
for i in data:
   if is_break:
      break # outer loop break
   for e in i:
      is_break = True
      break # inner loop break

-3

पहले की तरह ही, लेकिन अधिक कॉम्पैक्ट। (बूलियन सिर्फ नंबर हैं)

breaker = False #our mighty loop exiter!
while True:
    while True:
        ok = get_input("Is this ok? (y/n)")
        breaker+= (ok.lower() == "y")
        break

    if breaker: # the interesting part!
        break   # <--- !

2
यह बहुत बदसूरत लग रहा है और पिछले एक की तुलना में कोड को समझने में कठिन बनाता है। इसके अलावा, यह गलत है। यह वास्तव में जाँच करने से चूक जाता है कि इनपुट स्वीकार्य है और 1 लूप के बाद टूट जाता है।
एरिक

-3

चूंकि यह प्रश्न किसी विशेष लूप में टूटने के लिए एक मानक प्रश्न बन गया है, इसलिए मैं उदाहरण के साथ अपना जवाब देना चाहूंगा Exception

हालाँकि बहुप्रचलित लूप निर्माण में लूप ब्रेकिंग नाम का कोई लेबल मौजूद नहीं है, फिर भी हम अपनी पसंद के किसी विशेष लूप में तोड़ने के लिए उपयोगकर्ता-परिभाषित अपवादों का उपयोग कर सकते हैं । निम्नलिखित उदाहरण पर विचार करें जहां हम बेस -6 नंबरिंग सिस्टम में 4 अंक तक के सभी नंबरों को प्रिंट करते हैं:

class BreakLoop(Exception):
    def __init__(self, counter):
        Exception.__init__(self, 'Exception 1')
        self.counter = counter

for counter1 in range(6):   # Make it 1000
    try:
        thousand = counter1 * 1000
        for counter2 in range(6):  # Make it 100
            try:
                hundred = counter2 * 100
                for counter3 in range(6): # Make it 10
                    try:
                        ten = counter3 * 10
                        for counter4 in range(6):
                            try:
                                unit = counter4
                                value = thousand + hundred + ten + unit
                                if unit == 4 :
                                    raise BreakLoop(4) # Don't break from loop
                                if ten == 30: 
                                    raise BreakLoop(3) # Break into loop 3
                                if hundred == 500:
                                    raise BreakLoop(2) # Break into loop 2
                                if thousand == 2000:
                                    raise BreakLoop(1) # Break into loop 1

                                print('{:04d}'.format(value))
                            except BreakLoop as bl:
                                if bl.counter != 4:
                                    raise bl
                    except BreakLoop as bl:
                        if bl.counter != 3:
                            raise bl
            except BreakLoop as bl:
                if bl.counter != 2:
                    raise bl
    except BreakLoop as bl:
        pass

जब हम आउटपुट प्रिंट करते हैं, तो हमें कभी भी कोई मूल्य नहीं मिलेगा जिसका यूनिट स्थान 4 के साथ है। उस स्थिति में, हम किसी भी लूप से नहीं टूटते हैं BreakLoop(4)जैसा उठाया जाता है और उसी लूप में पकड़ा जाता है। इसी तरह, जब भी दस की जगह 3 होती है, हम तीसरे लूप का उपयोग करके टूट जाते हैं BreakLoop(3)। जब भी सौ का स्थान 5 होता है, हम दूसरे लूप का उपयोग करते हुए टूट जाते हैं BreakLoop(2)और जब भी हज़ार स्थान पर 2 होता है, हम पहले लूप का उपयोग करते हुए टूट जाते हैंBreakLoop(1)

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

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