पायथन में डू-ए-लूप का अनुकरण करें?


797

मुझे पायथन कार्यक्रम में एक लूप करते समय अनुकरण करने की आवश्यकता है। दुर्भाग्य से, निम्नलिखित सीधा कोड काम नहीं करता है:

list_of_ints = [ 1, 2, 3 ]
iterator = list_of_ints.__iter__()
element = None

while True:
  if element:
    print element

  try:
    element = iterator.next()
  except StopIteration:
    break

print "done"

"1,2,3, किया गया" के बजाय, यह निम्नलिखित आउटपुट प्रिंट करता है:

[stdout:]1
[stdout:]2
[stdout:]3
None['Traceback (most recent call last):
', '  File "test_python.py", line 8, in <module>
    s = i.next()
', 'StopIteration
']

'रोक पुनरावृत्ति' अपवाद को पकड़ने और थोड़ी देर के लूप को ठीक से तोड़ने के लिए मैं क्या कर सकता हूं?

इस तरह की चीज की आवश्यकता क्यों हो सकती है, इसका एक उदाहरण नीचे छद्मकोश के रूप में दिखाया गया है।

राज्य मशीन:

s = ""
while True :
  if state is STATE_CODE :
    if "//" in s :
      tokens.add( TOKEN_COMMENT, s.split( "//" )[1] )
      state = STATE_COMMENT
    else :
      tokens.add( TOKEN_CODE, s )
  if state is STATE_COMMENT :
    if "//" in s :
      tokens.append( TOKEN_COMMENT, s.split( "//" )[1] )
    else
      state = STATE_CODE
      # Re-evaluate same line
      continue
  try :
    s = i.next()
  except StopIteration :
    break

4
उम ... यह एक उचित "डू-टाइम" नहीं है; वह बस एक "हमेशा के लिए" है। "जबकि ट्रू" और "ब्रेक" में क्या गलत है?
S.Lott

70
एस। लोट: मुझे पूरा यकीन है कि उनका सवाल अजगर में रहते हुए कैसे लागू करना है। इसलिए, मुझे उम्मीद नहीं होगी कि उसका कोड पूरी तरह से सही होगा। इसके अलावा, वह ऐसा करने के लिए बहुत करीब है ... वह "हमेशा के लिए" लूप के अंत में एक शर्त की जांच कर रहा है कि क्या उसे बाहर तोड़ देना चाहिए। यह "करना-हमेशा के लिए" नहीं है।
टॉम

4
इसलिए ... आपका प्रारंभिक उदाहरण कोड वास्तव में मेरे लिए बिना किसी समस्या के काम करता है और मुझे वह ट्रेसबैक नहीं मिलता है। यह एक उचित मुहावरा है जबकि लूप के लिए जहां ब्रेक की स्थिति इटरेटर थकावट है। आमतौर पर, आप s=i.next()कोई भी नहीं के बजाय सेट करते हैं और संभवतः कुछ प्रारंभिक काम करते हैं, बजाय इसके कि आप अपना पहला पास लूप को बेकार कर दें।
underrun

3
@underrun दुर्भाग्य से, पोस्ट को टैग नहीं किया गया है कि पायथन के किस संस्करण का उपयोग किया जा रहा है - मूल स्निपेट मेरे लिए भी 2.7 का उपयोग कर काम करता है, संभवतः पायथन भाषा के अपडेट के कारण।
५५

जवाबों:


984

मुझे यकीन नहीं है कि आप क्या करने की कोशिश कर रहे हैं। आप इस तरह से एक लूप लागू कर सकते हैं:

while True:
  stuff()
  if fail_condition:
    break

या:

stuff()
while not fail_condition:
  stuff()

सूची में सामान को प्रिंट करने के लिए लूप करते समय आप क्या करने की कोशिश कर रहे हैं? सिर्फ उपयोग क्यों नहीं:

for i in l:
  print i
print "done"

अपडेट करें:

तो क्या आपके पास लाइनों की एक सूची है? और आप इसके माध्यम से पुनरावृति रखना चाहते हैं? कैसा रहेगा:

for s in l: 
  while True: 
    stuff() 
    # use a "break" instead of s = i.next()

क्या ऐसा लगता है कि आप क्या चाहते हैं? आपके कोड उदाहरण के साथ, यह होगा:

for s in some_list:
  while True:
    if state is STATE_CODE:
      if "//" in s:
        tokens.add( TOKEN_COMMENT, s.split( "//" )[1] )
        state = STATE_COMMENT
      else :
        tokens.add( TOKEN_CODE, s )
    if state is STATE_COMMENT:
      if "//" in s:
        tokens.append( TOKEN_COMMENT, s.split( "//" )[1] )
        break # get next s
      else:
        state = STATE_CODE
        # re-evaluate same line
        # continues automatically

1
मुझे एक राज्य मशीन बनाने की आवश्यकता है। राज्य मशीन में, CURRENT स्टेटमेंट का पुनर्मूल्यांकन करना एक सामान्य मामला है, इसलिए मुझे अगले आइटम की पुनरावृत्ति किए बिना 'जारी रखने' की आवश्यकता है। मैं नहीं जानता कि इस तरह की चीज़ों को 'फॉर s इन l:' इटर्शन :(? में कैसे करना है। 'लूप करते समय,' जारी 'वर्तमान आइटम का पुनर्मूल्यांकन करेगा, अंत में पुनरावृत्ति
grigoryvp

क्या आपका मतलब है कि आपको सूची में अपने स्थान पर नज़र रखने की आवश्यकता है? इस तरह जब आप उसी राज्य को वापस करते हैं, तो आप उठा सकते हैं कि आपने कहाँ छोड़ा था? थोड़ा और संदर्भ दीजिए। ऐसा लगता है जैसे आप सूची में एक सूचकांक का उपयोग करके बेहतर हो सकते हैं।
टॉम

धन्यवाद, मैंने आपके pseudocode पर टिप्पणी की ... आपका उदाहरण तब से खराब लग रहा है जब से आप "" संभालते हैं, ठीक उसी तरह से "कोई बात नहीं है कि आप किस राज्य में हैं। इसके अलावा, क्या यह वास्तविक कोड है जहां आप टिप्पणियों को संसाधित कर रहे हैं?" यदि आपके पास स्लैश के साथ तार हैं तो क्या होगा? यानी: प्रिंट "ब्लाह // <- क्या वह गड़बड़ करता है?"
टॉम

4
यह शर्म की बात है कि अजगर के पास लूप नहीं है। अजगर DRY है, एह?
Kr0e

43
आधिकारिक रुख / औचित्य के लिए PEP 315 को भी देखें : "भाषा के उपयोगकर्ताओं को सलाह दी जाती है कि वे जब-जब लूप उपयुक्त होते हैं, तब आंतरिक रूप से ट्रू-फॉर्म का उपयोग करें।"
dtk

310

यहाँ एक सरल तरीका है, जबकि लूप का अनुकरण करना है:

condition = True
while condition:
    # loop body here
    condition = test_loop_condition()
# end of loop

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


11
यह हमेशा एक अतिरिक्त बूलियन चर नहीं जोड़ता है। अक्सर ऐसा कुछ होता है, जो पहले से मौजूद होता है, जिसकी स्थिति का परीक्षण किया जा सकता है।
मार्टीन्यू

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

4
नोट: जबकि यह मूल प्रश्न को संबोधित करता है, यह दृष्टिकोण उपयोग करने की तुलना में कम लचीला है break। विशेष रूप से, अगर AFTER के लिए तर्क की आवश्यकता है test_loop_condition(), जो कि एक बार निष्पादित होने के बाद इसे निष्पादित नहीं किया जाना चाहिए, इसे अंदर लपेटना होगा if condition:। BTW, conditionअस्पष्ट है। अधिक वर्णनात्मक: moreया notDone
टूलमेकरसेव

7
@ कूलमेकरसिव मुझे असहमत करते हैं। मैं शायद ही कभी breakलूप में उपयोग करता हूं और जब मैं इसे कोड में सामना करता हूं जो मुझे बनाए रखता है तो मुझे पता चलता है कि लूप, सबसे अधिक बार, इसके बिना लिखा जा सकता था। प्रस्तुत समाधान, IMO है, जो अजगर में निर्माण करते समय एक प्रतिनिधित्व करने का सबसे स्पष्ट तरीका है।
nonsensickle

1
आदर्श रूप से, स्थिति को कुछ वर्णनात्मक नाम दिया जाएगा, जैसे has_no_errorsया end_reached(जिस स्थिति में लूप शुरू होगाwhile not end_reached
जोशायोडर-निष्क्रिय को छोड़कर ..

74

नीचे दिया गया मेरा कोड एक उपयोगी कार्यान्वयन हो सकता है, जो मुख्य अंतर को उजागर करता है बनाम जैसा मुझे समझ में आया।

तो इस एक मामले में, आप हमेशा कम से कम एक बार लूप से गुजरते हैं।

first_pass = True
while first_pass or condition:
    first_pass = False
    do_stuff()

2
सही जवाब, मैं बहस करता हूँ। इसके अलावा, यह टूटने से बचता है , कोशिश में सुरक्षित उपयोग के लिए / ब्लॉकों को छोड़कर।
Zv_oDD

क्या jit / optimizer पहले परीक्षण के बाद first_pass का पुन: परीक्षण करने से बचता है? अन्यथा, यह एक कष्टप्रद होगा, हालांकि शायद मामूली, प्रदर्शन का मुद्दा
markhahn

2
@markhahn यह वास्तव में बहुत ही कम हो, लेकिन अगर आप इस तरह के विवरण की परवाह है, तो आप पाश में 2 बूलियन्स intervert कर सकते हैं: while condition or first_pass:। फिर conditionहमेशा पहले मूल्यांकन किया जाता है और समग्र first_passका मूल्यांकन केवल दो बार (प्रथम और अंतिम पुनरावृत्ति) किया जाता है। conditionजो कुछ भी आप चाहते हैं उसके पहले लूप को इनिशियलाइज़ करना न भूलें ।
pLOPeGG

एचएम, दिलचस्प है कि मैंने वास्तव में दूसरे तरीके को चुना है ताकि जानबूझकर स्थिति को शुरू न किया जा सके और इस तरह कोड में न्यूनतम बदलाव की आवश्यकता हो। कहा कि मैं आपकी बात देखता हूं
evan54

33

अपवाद लूप को तोड़ देगा, इसलिए आप इसे लूप के बाहर भी संभाल सकते हैं।

try:
  while True:
    if s:
      print s
    s = i.next()
except StopIteration:   
  pass

मुझे लगता है कि आपके कोड के साथ समस्या यह है कि breakअंदर exceptका व्यवहार परिभाषित नहीं है। आम तौर पर breakकेवल एक स्तर ऊपर जाता है, इसलिए जैसे breakअंदर tryसीधे बाहर जाता है finally(यदि यह मौजूद है) एक से बाहर try, लेकिन लूप से बाहर नहीं।

संबंधित PEP: http://www.python.org/dev/peps/pep-3136
संबंधित प्रश्न: नेड लूप्स को तोड़ना


8
यह अच्छा अभ्यास है, हालांकि केवल कोशिश बयान के अंदर है कि आप अपने अपवाद को फेंकने की क्या उम्मीद करते हैं, ऐसा न हो कि आप अवांछित अपवादों को पकड़ लें।
पग्गस

7
@PPP: आरटीएफएम, ईएएफपी की खोज करें।
वार्टेक

2
@PiPeep: कोई बात नहीं, बस ध्यान रखें, कि कुछ भाषाओं के लिए क्या सच है, दूसरे के लिए सच नहीं हो सकता है। अपवादों के गहन उपयोग के लिए अजगर को अनुकूलित किया गया है।
16

5
तोड़ना और जारी रखना पूरी तरह से किसी भी कोशिश के खंड में परिभाषित किया गया है / छोड़कर / अंत में बयान। वे बस उन्हें अनदेखा करते हैं, और या तो बाहर तोड़ देते हैं या उचित के रूप में या लूप के लिए युक्त के अगले पुनरावृत्ति के लिए आगे बढ़ते हैं। लूपिंग के घटकों के रूप में, वे केवल कथन के लिए और उनके लिए प्रासंगिक होते हैं, और अगर वे अंतरतम लूप तक पहुँचने से पहले क्लास या डिफ स्टेटमेंट में चलते हैं तो एक सिंटैक्स त्रुटि को ट्रिगर करते हैं। वे अगर, साथ और बयानों को आजमाते हैं तो वे नजरअंदाज कर देते हैं।
ncoghlan

1
.. जो कि एक महत्वपूर्ण मामला है
javadba

33
do {
  stuff()
} while (condition())

->

while True:
  stuff()
  if not condition():
    break

आप एक समारोह कर सकते हैं:

def do_while(stuff, condition):
  while condition(stuff()):
    pass

लेकिन 1) यह बदसूरत है। 2) हालत एक पैरामीटर के साथ एक फ़ंक्शन होनी चाहिए, जिसे सामान द्वारा भरा जाना चाहिए (यह लूप करते समय क्लासिक का उपयोग करने का एकमात्र कारण है ।)


5
लेखन while True: stuff(); if not condition(): breakएक बहुत अच्छा विचार है। धन्यवाद!
नॉक्टिस स्काईटॉवर

2
@ZeD, क्यों 1) बदसूरत है? यह काफी ठीक है, IMHO
सर्गेई लॉससेव

@SergeyLossev कार्यक्रम के तर्क को समझ पाना मुश्किल होने वाला है क्योंकि यह पहली बार में एक अनंत लूप के रूप में प्रकट होता है, अगर आपके पास बीच में बहुत सारे 'सामान' कोड हैं।
निर्गमन

16

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

def coroutine(func):
    """Coroutine decorator

    Coroutines must be started, advanced to their first "yield" point,
    and this decorator does this automatically.
    """
    def startcr(*ar, **kw):
        cr = func(*ar, **kw)
        cr.next()
        return cr
    return startcr

@coroutine
def collector(storage):
    """Act as "sink" and collect all sent in @storage"""
    while True:
        storage.append((yield))

@coroutine      
def state_machine(sink):
    """ .send() new parts to be tokenized by the state machine,
    tokens are passed on to @sink
    """ 
    s = ""
    state = STATE_CODE
    while True: 
        if state is STATE_CODE :
            if "//" in s :
                sink.send((TOKEN_COMMENT, s.split( "//" )[1] ))
                state = STATE_COMMENT
            else :
                sink.send(( TOKEN_CODE, s ))
        if state is STATE_COMMENT :
            if "//" in s :
                sink.send(( TOKEN_COMMENT, s.split( "//" )[1] ))
            else
                state = STATE_CODE
                # re-evaluate same line
                continue
        s = (yield)

tokens = []
sm = state_machine(collector(tokens))
for piece in i:
    sm.send(piece)

कोड की जानकारी सब से ऊपर में tuples के रूप में टोकन tokensऔर मुझे लगता है वहाँ कोई अंतर नहीं है .append()और .add()मूल कोड में।


4
आज आप इसे पायथन 3.x में कैसे लिखेंगे?
नॉक्टिस स्काईटॉवर 20

13

जिस तरह से मैंने किया है वह इस प्रकार है ...

condition = True
while condition:
     do_stuff()
     condition = (<something that evaluates to True or False>)

यह मुझे सरलीकृत समाधान लगता है, मुझे आश्चर्य है कि मैंने इसे यहां पहले से नहीं देखा है। यह स्पष्ट रूप से भी उलटा हो सकता है

while not condition:

आदि।


आप कहते हैं, "मुझे आश्चर्य है कि मैंने इसे यहाँ पहले से ही नहीं देखा है" - लेकिन मुझे इससे कोई अंतर नहीं दिखता है, आइए बताते हैं, 2010 से पाउडरफ्लस्क का समाधान। यह बिल्कुल वैसा ही है। ("हालत = सच है जबकि हालत: # पाश शरीर यहाँ हालत = test_loop_condition () # लूप का अंत")
cslotty

10

एक के लिए - जबकि पाश कोशिश बयान युक्त

loop = True
while loop:
    generic_stuff()
    try:
        questionable_stuff()
#       to break from successful completion
#       loop = False  
    except:
        optional_stuff()
#       to break from unsuccessful completion - 
#       the case referenced in the OP's question
        loop = False
   finally:
        more_generic_stuff()

वैकल्पिक रूप से, जब 'अंत' खंड के लिए कोई आवश्यकता नहीं है

while True:
    generic_stuff()
    try:
        questionable_stuff()
#       to break from successful completion
#       break  
    except:
        optional_stuff()
#       to break from unsuccessful completion - 
#       the case referenced in the OP's question
        break

7
while condition is True: 
  stuff()
else:
  stuff()

8
Ew। यह एक ब्रेक का उपयोग करने की तुलना में काफी बदसूरत लगता है।
mattdm

5
यह चतुर है, लेकिन इसके लिए stuffएक फ़ंक्शन या कोड बॉडी को दोहराया जाना चाहिए।
नॉक्टिस स्काईटॉवर 20

12
सभी की जरूरत है while condition:क्योंकि is Trueनिहित है।
मार्टीन्यू

2
यह विफल रहता है अगर conditionकुछ आंतरिक चर पर निर्भर करता है stuff(), क्योंकि उस क्षण में उस चर को परिभाषित नहीं किया जाता है।
यो '

5
एक ही तर्क नहीं, क्योंकि अंतिम पुनरावृत्ति पर जब शर्त! = सत्य: यह कोड को अंतिम समय कहता है। जहां डू डू के रूप में, एक बार पहले कोड को कॉल करता है, फिर री-रनिंग से पहले स्थिति की जांच करता है। जबकि करें: एक बार ब्लॉक निष्पादित करें; फिर जाँच करें और फिर से चलाएं , यह उत्तर: जाँच करें और फिर से चलाएं; फिर एक बार कोड ब्लॉक निष्पादित करें । बड़ा अंतर!
Zv_oDD

7

त्वरित हैक:

def dowhile(func = None, condition = None):
    if not func or not condition:
        return
    else:
        func()
        while condition():
            func()

ऐसे उपयोग करें:

>>> x = 10
>>> def f():
...     global x
...     x = x - 1
>>> def c():
        global x
        return x > 0
>>> dowhile(f, c)
>>> print x
0

3

तुम बस क्यों नहीं करते

for s in l :
    print s
print "done"

?


1
मुझे एक राज्य मशीन बनाने की आवश्यकता है। राज्य मशीन में, CURRENT स्टेटमेंट का पुनर्मूल्यांकन करना एक सामान्य मामला है, इसलिए मुझे अगले आइटम की पुनरावृत्ति किए बिना 'जारी रखने' की आवश्यकता है। मैं नहीं जानता कि इस तरह की चीज़ों को 'फॉर एस इन एल:' इटर्शन :(? में कैसे करना है। '' लूप करते समय 'जारी' वर्तमान आइटम, पुनरावृत्ति का पुनर्मूल्यांकन करेगा।
grigoryvp

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

लूप के लिए काम नहीं करता है जैसे: a = fun () जबकि a == 'zxc': नींद (10) a = fun ()
harry

यह पूरी तरह से एक बूलियन स्थिति की जांच करने के बिंदु को याद करता है
javadba

1

देखें कि क्या यह मदद करता है:

अपवाद हैंडलर के अंदर एक ध्वज सेट करें और एस पर काम करने से पहले इसे जांचें।

flagBreak = false;
while True :

    if flagBreak : break

    if s :
        print s
    try :
        s = i.next()
    except StopIteration :
        flagBreak = true

print "done"

3
का उपयोग करके while not flagBreak:और हटाकर सरल बनाया जा सकता है if (flagBreak) : break
मार्टीन्यू

1
मैं नामित चर से बचता हूं flag- मैं यह मानने में असमर्थ हूं कि एक सही मूल्य या गलत मूल्य क्या है। इसके बजाय, का उपयोग करें doneया endOfIteration। कोड में बदल जाता है while not done: ...
IceArdor

1

यदि आप एक ऐसे परिदृश्य में हैं जहाँ आप संसाधन की अनुपलब्धता के दौरान लूपिंग कर रहे हैं या ऐसा ही कुछ है जो एक अपवाद को फेंकता है, तो आप कुछ का उपयोग कर सकते हैं

import time

while True:
    try:
       f = open('some/path', 'r')
    except IOError:
       print('File could not be read. Retrying in 5 seconds')   
       time.sleep(5)
    else:
       break

0

मेरे लिए एक विशिष्ट जबकि लूप कुछ इस तरह होगा:

xBool = True
# A counter to force a condition (eg. yCount = some integer value)

while xBool:
    # set up the condition (eg. if yCount > 0):
        (Do something)
        yCount = yCount - 1
    else:
        # (condition is not met, set xBool False)
        xBool = False

मैं एक for..loop जबकि लूप के भीतर भी शामिल कर सकता हूं , यदि स्थिति इतनी वारंट है, तो शर्त के एक और सेट के माध्यम से लूपिंग के लिए।

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