पैदावार का उपयोग करके पुनरावृत्ति


84

क्या पुनरावृत्ति और yieldकथन को मिलाने का कोई तरीका है ? उदाहरण के लिए, एक अनंत संख्या जनरेटर (पुनरावृत्ति का उपयोग करके) कुछ इस तरह होगा:

def infinity(start):
    yield start
    # recursion here ...

>>> it = infinity(1)
>>> next(it)
1
>>> next(it)
2

मैंने कोशिश की:

def infinity(start):
    yield start
    infinity(start + 1)

तथा

def infinity(start):
    yield start
    yield infinity(start + 1)

लेकिन उनमें से किसी ने भी ऐसा नहीं किया जो मैं चाहता हूं, पहले एक के बाद यह बंद हो गया startऔर दूसरे ने उपज प्राप्त की start, फिर जनरेटर और फिर बंद हो गया।

नोट: कृपया, मुझे पता है कि आप एक लूप का उपयोग करके ऐसा कर सकते हैं:

def infinity(start):
    while True:
        yield start
        start += 1

मैं सिर्फ यह जानना चाहता हूं कि क्या यह पुनरावर्ती रूप से किया जा सकता है।


इस प्रश्न के अच्छे उत्तर के लिए [१] [१] देखें, मैंने कुछ समय पहले लिखा था। [१]: stackoverflow.com/questions/5704220/…
sizzzzlerz

नोट: ऐसा करने का उचित तरीका यह होगा कि आप itertools.countअपने स्वयं के समाधान, लूप-आधारित या अन्य के रोल के बजाय उपयोग करें ।
पेट्र विक्टोरिन

8
@PetrViktorin यह केवल एक उदाहरण है, अनंत संख्या उत्पन्न करना वास्तविक समस्या नहीं है
जूलियोमेलेग्रिया

जवाबों:


157

हां, आप यह कर सकते हैं:

def infinity(start):
    yield start
    for x in infinity(start + 1):
        yield x

हालांकि अधिकतम पुनरावृत्ति गहराई तक पहुंचने के बाद यह त्रुटि हो जाएगी।

पायथन 3.3 से शुरू, आप उपयोग करने में सक्षम होंगे

def infinity(start):
    yield start
    yield from infinity(start + 1)

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

देखें पीईपी 380 अधिक जानकारी के लिए।


13
लेकिन ऐसा लगता है yield fromकि अभी भी एक पुनरावृत्ति सीमा है :(
जो तो

3
हमेशा एक पुनरावर्ती सीमा होगी
रेडियो नियंत्रित

12

कुछ मामलों में जनरेटर के लिए पुनरावृत्ति के बजाय स्टैक का उपयोग करना बेहतर हो सकता है। स्टैक और थोड़ी देर लूप का उपयोग करके एक पुनरावर्ती विधि को फिर से लिखना संभव होना चाहिए।

यहाँ एक पुनरावर्ती विधि का उदाहरण दिया गया है जो कॉलबैक का उपयोग करता है और स्टैक लॉजिक का उपयोग करके इसे फिर से लिखा जा सकता है:

def traverse_tree(callback):
    # Get the root node from somewhere.
    root = get_root_node()
    def recurse(node):
        callback(node)
        for child in node.get('children', []):
            recurse(child)
    recurse(root)

उपरोक्त विधि एक नोड ट्री का पता लगाती है जहां प्रत्येक नोड में एक childrenसरणी होती है जिसमें बच्चे के नोड हो सकते हैं। जैसा कि प्रत्येक नोड का सामना किया जाता है, कॉलबैक जारी किया जाता है और वर्तमान नोड को इसे पास किया जाता है।

इस पद्धति का उपयोग इस प्रकार किया जा सकता है, प्रत्येक नोड पर कुछ संपत्ति को प्रिंट करना।

def callback(node):
    print(node['id'])
traverse_tree(callback)

इसके बजाय एक स्टैक का उपयोग करें और एक जनरेटर के रूप में ट्रैवर्सल विधि लिखें

# A stack-based alternative to the traverse_tree method above.
def iternodes():
    stack = [get_root_node()]
    while stack:
        node = stack.pop()
        yield node
        for child in reversed(node.get('children', [])):
            stack.append(child)

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

अब आप traverse_treeऊपर जैसा व्यवहार कर सकते हैं , लेकिन एक जनरेटर के साथ:

for node in iternodes():
    print(node['id'])

यह एक आकार-फिट-सभी समाधान नहीं है, लेकिन कुछ जनरेटर के लिए आपको पुनरावर्तन के लिए स्टैक प्रसंस्करण का एक अच्छा परिणाम मिल सकता है।


3
अच्छा उत्तर! अजगर 2.7 में यील्ड वास्तव में पुनरावृत्ति के साथ उपयोग नहीं किया जा सकता है, लेकिन स्टैक को मैन्युअल रूप से प्रबंधित करके आप एक ही प्रभाव प्राप्त कर सकते हैं।
20p पर 00prometheus

0
def lprint(a):
    if isinstance(a, list):
        for i in a:
            yield from lprint(i)
    else:
        yield a

b = [[1, [2, 3], 4], [5, 6, [7, 8, [9]]]]
for i in lprint(b):
    print(i)

क्या है b? कोड-केवल उत्तरों को न छोड़ने का प्रयास करें ... थोड़ा स्पष्टीकरण और स्पष्टीकरण चीजों को संदर्भ में रखने और आपके उत्तर को बेहतर ढंग से समझने में मदद करेगा
Tomerikoo

lprint में मैं के लिए (क): प्रिंट (i)
Юрий Блинков

उत्तर को संपादित क्यों नहीं किया गया, इसलिए यह अधिक स्पष्ट है? आप editअपने उत्तर के नीचे छोटे टैग पर क्लिक करके या यहां क्लिक करके कर सकते हैं । इसके अलावा, जैसा कि मैंने कहा कि कैसे और क्यों इस समस्या को हल करने के लिए एक छोटी सी व्याख्या जोड़ने की कोशिश
Tomerikoo

-3

तो मूल रूप से आपको बस एक लूप जोड़ने की जरूरत है जहां आपको अपने फ़ंक्शन को पुनरावर्ती रूप से कॉल करने की आवश्यकता है । यह पायथन 2.7 के लिए लागू होता है।


1
हालाँकि इस उत्तर के लिए अधिक विवरण की आवश्यकता है, यह वास्तव में स्वेन मार्नाच के स्वीकृत उत्तर के अनुरूप है, देखें उनका पहला कोड ...
Coffee_Table
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.