पायथन पुनरावृत्तियों में कोई पाठ नहीं है?


जवाबों:


106

नहीं, ऐसी कोई विधि नहीं है। पुनरावृत्ति का अंत एक अपवाद द्वारा इंगित किया गया है। दस्तावेज देखें ।


71
"अनुमति की तुलना में माफी मांगना आसान है।"

118
"अनुमति की तुलना में माफी माँगना अधिक आसान है।": यह जाँचना कि क्या एक इटैलर में अगला तत्व है, अनुमति के लिए नहीं पूछ रहा है। ऐसी परिस्थितियां हैं जिनमें आप बिना उपभोग किए अगले तत्व के अस्तित्व के लिए परीक्षण करना चाहते हैं। अगर unnext()मैं जाँच करने के बाद पहले तत्व को वापस लाने की कोई विधि थी, तो मैं कोशिश करूँगा कि अगर वह कॉल करके मौजूद है, तो मैं उसे पकड़ लूंगा next()
जियोर्जियो

15
@ जिओर्जियो, यह जानने का कोई तरीका नहीं है कि क्या कोड को निष्पादित किए बिना एक और तत्व मौजूद है जो इसे उत्पन्न करता है (आप नहीं जानते कि जनरेटर निष्पादित करेगा yieldया नहीं)। बेशक, एक एडेप्टर लिखना मुश्किल नहीं है जो परिणाम next()प्रदान करता है has_next()और प्रदान करता है और move_next()
अवकर

5
एक ही विचार का उपयोग hasNext()विधि को लागू करने के लिए किया जा सकता है (उत्पादन, कैश करने और सफलता पर सही होने के लिए, या असफलता पर गलत वापसी)। फिर दोनों hasNext()और next()एक आम अंतर्निहित पर निर्भर करेगा getNext()विधि और कैश की गई मद। मैं वास्तव में यह नहीं देखता कि next()मानक पुस्तकालय में क्यों नहीं होना चाहिए अगर यह एक एडाप्टर को लागू करना इतना आसान है जो इसे प्रदान करता है।
जियोर्जियो

3
@ लार्स: आपका मतलब है कि एक ऐसा इटरेटर जो किसी फ़ाइल से पढ़ता है जिसे उससे पढ़ते समय बदला जा सकता है? मैं सहमत हूं कि यह एक समस्या हो सकती है (जो किसी भी पुस्तकालय को प्रदान करने next()और hasNext()विधि को प्रभावित करती है , न कि केवल एक काल्पनिक पायथन पुस्तकालय को)। तो हां, next()और hasNext()अगर ट्रिक की सामग्री स्कैन की जा रही है तो यह निर्भर करता है कि तत्वों को कब पढ़ा जाता है।
जियोर्जियो

239

का StopIterationउपयोग करके एक विकल्प है next(iterator, default_value)

निर्वासन के लिए:

>>> a = iter('hi')
>>> print next(a, None)
h
>>> print next(a, None)
i
>>> print next(a, None)
None

Noneयदि आप अपवाद के तरीके को नहीं चाहते हैं, तो आप पुनरावृत्त के अंत के लिए या अन्य पूर्व-निर्दिष्ट मान का पता लगा सकते हैं।


70
यदि आप किसी को भी "प्रहरी" के रूप में उपयोग नहीं करते हैं, तो आपको सबसे अच्छा यकीन है कि आपके पुनरावृत्त में कोई भी नहीं है। आप भी कर सकते हैं sentinel = object()और next(iterator, sentinel)साथ परीक्षण कर सकते हैं is
सैम बोसालिस 18

1
निम्नलिखित @samboosalis मैं बल्कि अंतर्निहित unittest.mock.sentinelवस्तु का उपयोग करूंगा जो आपको एक स्पष्ट next(a, sentinel.END_OF_ITERATION)और फिर लिखने की अनुमति देता हैif next(...) == sentinel.END_OF_ITERATION
क्लेमेंटवैल्टर

यह अपवाद से अधिक
पुराना

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

39

यदि आपको वास्तव में एक कार्यक्षमता की आवश्यकता है has-next(क्योंकि आप जावा में संदर्भ कार्यान्वयन से एक एल्गोरिदम का ईमानदारी से रूपांतरण कर रहे हैं, तो कहिए, या क्योंकि आप एक प्रोटोटाइप लिख रहे हैं जिसे समाप्त होने पर आसानी से जावा में स्थानांतरित करना होगा), यह आसान है इसे थोड़ा रैपर क्लास के साथ प्राप्त करें। उदाहरण के लिए:

class hn_wrapper(object):
  def __init__(self, it):
    self.it = iter(it)
    self._hasnext = None
  def __iter__(self): return self
  def next(self):
    if self._hasnext:
      result = self._thenext
    else:
      result = next(self.it)
    self._hasnext = None
    return result
  def hasnext(self):
    if self._hasnext is None:
      try: self._thenext = next(self.it)
      except StopIteration: self._hasnext = False
      else: self._hasnext = True
    return self._hasnext

अब कुछ ऐसा है

x = hn_wrapper('ciao')
while x.hasnext(): print next(x)

का उत्सर्जन करता है

c
i
a
o

जैसी ज़रूरत।

ध्यान दें कि next(sel.it)एक अंतर्निहित अंतर्निहित पायथन 2.6 या बेहतर की आवश्यकता होती है; यदि आप पायथन के पुराने संस्करण का उपयोग कर रहे हैं, तो self.it.next()इसके बजाय का उपयोग करें (और next(x)उदाहरण के उपयोग के लिए इसी तरह )। [[आप यथोचित रूप से सोच सकते हैं कि यह नोट निरर्थक है, क्योंकि पायथन २.६ अब एक साल से अधिक समय से है - लेकिन अधिक बार नहीं जब मैं एक प्रतिक्रिया में पायथन २.६ सुविधाओं का उपयोग करता हूं, कुछ टिप्पणीकार या अन्य को इंगित करने के लिए ड्यूटी-बाउंड लगता है वे कहते हैं कि कर रहे हैं 2.6 सुविधाओं, इस प्रकार मैं एक बार ;-)]] के लिए इस तरह की टिप्पणियां रोकने के लिए कोशिश कर रहा हूँ


9
"विश्वासपूर्वक जावा में एक संदर्भ कार्यान्वयन से एक एल्गोरिथ्म को स्थानांतरित करना" एक has_nextविधि की आवश्यकता का सबसे खराब कारण है । पायथन के डिजाइन से यह कहना, असंभव हो जाता है कि filterकिसी सरणी में दिए गए एलीमेंट से मेल खाता तत्व है या नहीं। अजगर समुदाय का अहंकार और अदूरदर्शिता चौंका देने वाला है।
जोनाथन

अच्छा जवाब, मैं इसे जावा कोड से लिए गए कुछ डिज़ाइन पैटर्न के
ustustration के

मैं Python3 के साथ हूँ और यह कोड मुझे देता हैTypeError: iter() returned non-iterator
madtyn

1
@JonathanCast सुनिश्चित नहीं है कि मैं अनुसरण करता हूं। पायथन में, आप आमतौर पर उपयोग करते हैं mapऔर anyइसके बजाय filter, लेकिन आप उपयोग कर सकते हैं SENTINEL = object(); next(filter(predicate, arr), SENTINEL) is not SENTINELया एक भूल सकते हैं SENTINELऔर बस उपयोग कर सकते हैं try: exceptऔर पकड़ सकते हैं StopIteration
juanpa.arrivillaga

13

StopIteration के सभी उल्लेखों के अलावा, "पाश" के लिए पायथन बस वही करता है जो आप चाहते हैं:

>>> it = iter("hello")
>>> for i in it:
...     print i
...
h
e
l
l
o

7

किसी भी वस्तु वस्तु से __length_hint __ () विधि आज़माएं:

iter(...).__length_hint__() > 0

5
मैं हमेशा सोचता था कि पृथ्वी पर अजगर के पास __ xxx __ विधियां क्यों हैं? वे इतने बदसूरत लगते हैं।
एम.पी.

6
वैध प्रश्न! आमतौर पर यह उन तरीकों के लिए वाक्यविन्यास है जो एक बेसिन फ़ंक्शन (जैसे लेन, वास्तव में लेन कह रहा है ) द्वारा उजागर होते हैं । इस तरह का बिल्टइन फंक्शन length_hint के लिए मौजूद नहीं है, लेकिन यह वास्तव में एक लंबित प्रस्ताव (PEP424) है।
फुलिमोटन

1
@एमपी। ये कार्य हैं, क्योंकि कभी-कभी इनकी आवश्यकता होती है। वे जानबूझकर बदसूरत हैं, क्योंकि उन्हें अंतिम उपाय की विधि के रूप में समझा जाता है: यदि आप उनका उपयोग करते हैं, तो आप जानते हैं कि आप कुछ गैर-पायथोनिक और संभावित रूप से खतरनाक करते हैं (जो किसी भी बिंदु पर काम करना बंद कर सकते हैं)।
अर्ने बाबोनहॉसरहाइड

जैसा __init__और __main__? Imho, यह एक गड़बड़ का कोई फर्क नहीं पड़ता कि आप इसे सही ठहराने की कोशिश करते हैं।
user1363990

5

hasNextStopIterationअपवाद के लिए कुछ अनुवाद , उदाहरण के लिए:

>>> it = iter("hello")
>>> it.next()
'h'
>>> it.next()
'e'
>>> it.next()
'l'
>>> it.next()
'l'
>>> it.next()
'o'
>>> it.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

4

आप teeitter का उपयोग कर सकते हैं itertools.tee, और StopIterationteed iterator पर जाँच कर सकते हैं।


3

नहीं। सबसे समान अवधारणा सबसे अधिक संभावना है एक स्टॉपइंटरेशन अपवाद।


10
नियंत्रण प्रवाह के लिए पायथन अपवादों का क्या उपयोग करता है? बहुत भद्दा लगता है।
एम.पी.

5
सही: अपवादों का उपयोग त्रुटियों को संभालने के लिए किया जाना चाहिए, न कि नियंत्रण के सामान्य प्रवाह को परिभाषित करने के लिए।
जियोर्जियो


1

उपयोग मामला जो मुझे इसके लिए खोज करने के लिए प्रेरित करता है वह निम्नलिखित है

def setfrom(self,f):
    """Set from iterable f"""
    fi = iter(f)
    for i in range(self.n):
        try:
            x = next(fi)
        except StopIteration:
            fi = iter(f)
            x = next(fi)
        self.a[i] = x 

जहाँ hasnext () उपलब्ध है, कोई भी कर सकता है

def setfrom(self,f):
    """Set from iterable f"""
    fi = iter(f)
    for i in range(self.n):
        if not hasnext(fi):
            fi = iter(f) # restart
        self.a[i] = next(fi)

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

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


1
इस उपयोग के मामले के लिए, आप itertools.cycle
eaglebrain

0

सुझाव दिया रास्ता StopIteration है । कृपया ट्यूटोरियल स्पॉट से फाइबोनैचि उदाहरण देखें

#!usr/bin/python3

import sys
def fibonacci(n): #generator function
   a, b, counter = 0, 1, 0
   while True:
      if (counter > n): 
         return
      yield a
      a, b = b, a + b
      counter += 1
f = fibonacci(5) #f is iterator object

while True:
   try:
      print (next(f), end=" ")
   except StopIteration:
      sys.exit()

-2

जिस तरह से मैंने अपनी समस्या को हल किया है वह यह है कि अब तक पुनरावृत्त वस्तुओं की संख्या को ध्यान में रखा जाए। मैं एक उदाहरण विधि के लिए कॉल का उपयोग करते हुए एक सेट पर पुनरावृति करना चाहता था। चूंकि मुझे सेट की लंबाई पता थी, और अब तक गिने जाने वाले आइटमों की संख्या, मेरे पास प्रभावी रूप से एक hasNextविधि थी।

मेरे कोड का एक सरल संस्करण:

class Iterator:
    # s is a string, say
    def __init__(self, s):
        self.s = set(list(s))
        self.done = False
        self.iter = iter(s)
        self.charCount = 0

    def next(self):
        if self.done:
            return None
        self.char = next(self.iter)
        self.charCount += 1
        self.done = (self.charCount < len(self.s))
        return self.char

    def hasMore(self):
        return not self.done

बेशक, उदाहरण एक खिलौना है, लेकिन आपको यह विचार मिलता है। यह उन मामलों में काम नहीं करेगा, जहां चलने योग्य की लंबाई प्राप्त करने का कोई तरीका नहीं है, जैसे जनरेटर आदि।

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